@alfadocs/ui-kit-debug 0.63.0 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/_chunks/{ai-prompt-input-C6sCr1Vi.js → ai-prompt-input-Dx8eXoPm.js} +2 -2
  2. package/dist/_chunks/{ai-prompt-input-C6sCr1Vi.js.map → ai-prompt-input-Dx8eXoPm.js.map} +1 -1
  3. package/dist/_chunks/{audio-recorder-D6OVfNiZ.js → audio-recorder-CdXuT9ln.js} +2 -2
  4. package/dist/_chunks/{audio-recorder-D6OVfNiZ.js.map → audio-recorder-CdXuT9ln.js.map} +1 -1
  5. package/dist/_chunks/{bishop-score-B9tvgoIq.js → bishop-score-CzjSx-dm.js} +2 -2
  6. package/dist/_chunks/{bishop-score-B9tvgoIq.js.map → bishop-score-CzjSx-dm.js.map} +1 -1
  7. package/dist/_chunks/{booking-BUV9fspj.js → booking-ChfvWy3P.js} +2 -2
  8. package/dist/_chunks/{booking-BUV9fspj.js.map → booking-ChfvWy3P.js.map} +1 -1
  9. package/dist/_chunks/{care-plan-card-QmNpGggC.js → care-plan-card-DhZNoXs4.js} +2 -2
  10. package/dist/_chunks/{care-plan-card-QmNpGggC.js.map → care-plan-card-DhZNoXs4.js.map} +1 -1
  11. package/dist/_chunks/{care-plan-entry-card-Cnra7vUc.js → care-plan-entry-card-DW70yBOD.js} +2 -2
  12. package/dist/_chunks/{care-plan-entry-card-Cnra7vUc.js.map → care-plan-entry-card-DW70yBOD.js.map} +1 -1
  13. package/dist/_chunks/{editable-currency-cell-renderer-D5C5tCfu.js → editable-currency-cell-renderer-BQgaKFCz.js} +2 -2
  14. package/dist/_chunks/{editable-currency-cell-renderer-D5C5tCfu.js.map → editable-currency-cell-renderer-BQgaKFCz.js.map} +1 -1
  15. package/dist/_chunks/{gestational-age-calculator-AkNFfZYs.js → gestational-age-calculator-D85E8lGN.js} +2 -2
  16. package/dist/_chunks/{gestational-age-calculator-AkNFfZYs.js.map → gestational-age-calculator-D85E8lGN.js.map} +1 -1
  17. package/dist/_chunks/{pregnancy-dating-Dg6dTe1p.js → pregnancy-dating-7NUaAfob.js} +2 -2
  18. package/dist/_chunks/{pregnancy-dating-Dg6dTe1p.js.map → pregnancy-dating-7NUaAfob.js.map} +1 -1
  19. package/dist/_chunks/{select-hsCaJSX3.js → select-CEtRcon5.js} +46 -45
  20. package/dist/_chunks/select-CEtRcon5.js.map +1 -0
  21. package/dist/_chunks/{tabs-BpPYVme_.js → tabs-BIQ0ew1T.js} +2 -2
  22. package/dist/_chunks/{tabs-BpPYVme_.js.map → tabs-BIQ0ew1T.js.map} +1 -1
  23. package/dist/_chunks/tooth-scheme-CiphQaON.js +1257 -0
  24. package/dist/_chunks/tooth-scheme-CiphQaON.js.map +1 -0
  25. package/dist/_chunks/{unit-converter-3sINXO3m.js → unit-converter-BIbXHIQA.js} +2 -2
  26. package/dist/_chunks/{unit-converter-3sINXO3m.js.map → unit-converter-BIbXHIQA.js.map} +1 -1
  27. package/dist/agent-catalog.json +41 -4
  28. package/dist/components/ai-prompt-input/index.js +1 -1
  29. package/dist/components/audio-recorder/index.js +1 -1
  30. package/dist/components/bishop-score/index.js +1 -1
  31. package/dist/components/booking/index.js +1 -1
  32. package/dist/components/care-plan-card/index.js +1 -1
  33. package/dist/components/care-plan-entry-card/index.js +1 -1
  34. package/dist/components/data-table/index.js +1 -1
  35. package/dist/components/gestational-age-calculator/index.js +1 -1
  36. package/dist/components/pregnancy-dating/index.js +1 -1
  37. package/dist/components/select/index.js +1 -1
  38. package/dist/components/select/select.d.ts +8 -0
  39. package/dist/components/select/select.d.ts.map +1 -1
  40. package/dist/components/tabs/index.js +1 -1
  41. package/dist/components/tooth-scheme/index.d.ts +2 -2
  42. package/dist/components/tooth-scheme/index.d.ts.map +1 -1
  43. package/dist/components/tooth-scheme/index.js +22 -15
  44. package/dist/components/tooth-scheme/tooth-data.d.ts +79 -18
  45. package/dist/components/tooth-scheme/tooth-data.d.ts.map +1 -1
  46. package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts +2 -0
  47. package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts.map +1 -1
  48. package/dist/components/tooth-scheme/tooth-scheme.d.ts +48 -1
  49. package/dist/components/tooth-scheme/tooth-scheme.d.ts.map +1 -1
  50. package/dist/components/unit-converter/index.js +1 -1
  51. package/dist/i18n/locales/ar.d.ts +17 -0
  52. package/dist/i18n/locales/ar.d.ts.map +1 -1
  53. package/dist/i18n/locales/ar.js +18 -1
  54. package/dist/i18n/locales/ar.js.map +1 -1
  55. package/dist/i18n/locales/de.d.ts +17 -0
  56. package/dist/i18n/locales/de.d.ts.map +1 -1
  57. package/dist/i18n/locales/de.js +18 -1
  58. package/dist/i18n/locales/de.js.map +1 -1
  59. package/dist/i18n/locales/el.d.ts +17 -0
  60. package/dist/i18n/locales/el.d.ts.map +1 -1
  61. package/dist/i18n/locales/el.js +18 -1
  62. package/dist/i18n/locales/el.js.map +1 -1
  63. package/dist/i18n/locales/en.d.ts +17 -0
  64. package/dist/i18n/locales/en.d.ts.map +1 -1
  65. package/dist/i18n/locales/en.js +18 -1
  66. package/dist/i18n/locales/en.js.map +1 -1
  67. package/dist/i18n/locales/es.d.ts +17 -0
  68. package/dist/i18n/locales/es.d.ts.map +1 -1
  69. package/dist/i18n/locales/es.js +18 -1
  70. package/dist/i18n/locales/es.js.map +1 -1
  71. package/dist/i18n/locales/fr.d.ts +17 -0
  72. package/dist/i18n/locales/fr.d.ts.map +1 -1
  73. package/dist/i18n/locales/fr.js +18 -1
  74. package/dist/i18n/locales/fr.js.map +1 -1
  75. package/dist/i18n/locales/hi.d.ts +17 -0
  76. package/dist/i18n/locales/hi.d.ts.map +1 -1
  77. package/dist/i18n/locales/hi.js +18 -1
  78. package/dist/i18n/locales/hi.js.map +1 -1
  79. package/dist/i18n/locales/it.d.ts +17 -0
  80. package/dist/i18n/locales/it.d.ts.map +1 -1
  81. package/dist/i18n/locales/it.js +18 -1
  82. package/dist/i18n/locales/it.js.map +1 -1
  83. package/dist/i18n/locales/ja.d.ts +17 -0
  84. package/dist/i18n/locales/ja.d.ts.map +1 -1
  85. package/dist/i18n/locales/ja.js +18 -1
  86. package/dist/i18n/locales/ja.js.map +1 -1
  87. package/dist/i18n/locales/nl.d.ts +17 -0
  88. package/dist/i18n/locales/nl.d.ts.map +1 -1
  89. package/dist/i18n/locales/nl.js +18 -1
  90. package/dist/i18n/locales/nl.js.map +1 -1
  91. package/dist/i18n/locales/pl.d.ts +17 -0
  92. package/dist/i18n/locales/pl.d.ts.map +1 -1
  93. package/dist/i18n/locales/pl.js +18 -1
  94. package/dist/i18n/locales/pl.js.map +1 -1
  95. package/dist/i18n/locales/pt.d.ts +17 -0
  96. package/dist/i18n/locales/pt.d.ts.map +1 -1
  97. package/dist/i18n/locales/pt.js +18 -1
  98. package/dist/i18n/locales/pt.js.map +1 -1
  99. package/dist/i18n/locales/ro.d.ts +17 -0
  100. package/dist/i18n/locales/ro.d.ts.map +1 -1
  101. package/dist/i18n/locales/ro.js +18 -1
  102. package/dist/i18n/locales/ro.js.map +1 -1
  103. package/dist/i18n/locales/ru.d.ts +17 -0
  104. package/dist/i18n/locales/ru.d.ts.map +1 -1
  105. package/dist/i18n/locales/ru.js +18 -1
  106. package/dist/i18n/locales/ru.js.map +1 -1
  107. package/dist/i18n/locales/sq.d.ts +17 -0
  108. package/dist/i18n/locales/sq.d.ts.map +1 -1
  109. package/dist/i18n/locales/sq.js +18 -1
  110. package/dist/i18n/locales/sq.js.map +1 -1
  111. package/dist/i18n/locales/sv.d.ts +17 -0
  112. package/dist/i18n/locales/sv.d.ts.map +1 -1
  113. package/dist/i18n/locales/sv.js +18 -1
  114. package/dist/i18n/locales/sv.js.map +1 -1
  115. package/dist/i18n/locales/tr.d.ts +17 -0
  116. package/dist/i18n/locales/tr.d.ts.map +1 -1
  117. package/dist/i18n/locales/tr.js +18 -1
  118. package/dist/i18n/locales/tr.js.map +1 -1
  119. package/dist/i18n/locales/zh.d.ts +17 -0
  120. package/dist/i18n/locales/zh.d.ts.map +1 -1
  121. package/dist/i18n/locales/zh.js +18 -1
  122. package/dist/i18n/locales/zh.js.map +1 -1
  123. package/dist/index.js +180 -173
  124. package/dist/locales/ar.json +18 -1
  125. package/dist/locales/de.json +18 -1
  126. package/dist/locales/el.json +18 -1
  127. package/dist/locales/en.json +18 -1
  128. package/dist/locales/es.json +18 -1
  129. package/dist/locales/fr.json +18 -1
  130. package/dist/locales/hi.json +18 -1
  131. package/dist/locales/it.json +18 -1
  132. package/dist/locales/ja.json +18 -1
  133. package/dist/locales/nl.json +18 -1
  134. package/dist/locales/pl.json +18 -1
  135. package/dist/locales/pt.json +18 -1
  136. package/dist/locales/ro.json +18 -1
  137. package/dist/locales/ru.json +18 -1
  138. package/dist/locales/sq.json +18 -1
  139. package/dist/locales/sv.json +18 -1
  140. package/dist/locales/tr.json +18 -1
  141. package/dist/locales/zh.json +18 -1
  142. package/dist/tokens.css +1 -1
  143. package/package.json +1 -1
  144. package/dist/_chunks/select-hsCaJSX3.js.map +0 -1
  145. package/dist/_chunks/tooth-scheme-CxlsLjfN.js +0 -753
  146. package/dist/_chunks/tooth-scheme-CxlsLjfN.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"editable-currency-cell-renderer-D5C5tCfu.js","sources":["../../node_modules/lucide-react/dist/esm/icons/columns-2.js","../../src/components/data-table/toolbar.tsx","../../src/components/data-table/filters/text-filter.tsx","../../src/components/data-table/data-table.agent.ts","../../src/components/data-table/data-table.tsx","../../src/components/data-table/hooks/use-total-row.ts","../../src/components/data-table/filters/date-range-filter.tsx","../../src/components/data-table/filters/select-filter.tsx","../../src/components/data-table/filters/typeahead-filter.tsx","../../src/components/data-table/filters/number-filter.tsx","../../src/components/data-table/cell-renderers/status-cell-renderer.tsx","../../src/components/data-table/cell-renderers/user-cell-renderer.tsx","../../src/components/data-table/cell-renderers/image-cell-renderer.tsx","../../src/components/data-table/cell-renderers/tag-list-cell-renderer.tsx","../../src/components/data-table/cell-renderers/date-cell-renderer.tsx","../../src/components/data-table/cell-renderers/currency-cell-renderer.tsx","../../src/components/data-table/cell-renderers/actions-cell-renderer.tsx","../../src/components/data-table/cell-renderers/link-cell-renderer.tsx","../../src/components/data-table/cell-renderers/toggle-cell-renderer.tsx","../../src/components/data-table/cell-renderers/color-dot-cell-renderer.tsx","../../src/components/data-table/cell-renderers/balance-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-text-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-currency-cell-renderer.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }]\n];\nconst Columns2 = createLucideIcon(\"columns-2\", __iconNode);\n\nexport { __iconNode, Columns2 as default };\n//# sourceMappingURL=columns-2.js.map\n","import {\n cloneElement,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Columns,\n Download,\n FileSpreadsheet,\n FileText,\n GripVertical,\n Printer,\n RefreshCw,\n Search,\n X,\n} from 'lucide-react';\nimport type { FilterChangedEvent, GridApi } from 'ag-grid-community';\nimport { Button, type ButtonProps } from '../button/button';\nimport { IconButton, type IconButtonProps } from '../button/icon-button';\nimport { Popover } from '../popover/popover';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { TextInput } from '../text-input';\nimport { Tag } from '../tag';\nimport { DropdownMenu } from '../dropdown-menu';\n\n// Lucide icons default to 24×24 regardless of the wrapping span size, so\n// Button's `startIcon` slot (size-4 span) can't shrink them. Coerce icon\n// nodes to the `sm` button's 16px rendered size before handing them off.\nfunction sizeIcon(node: ReactNode): ReactNode {\n if (!isValidElement(node)) return node;\n const element = node as React.ReactElement<{\n className?: string;\n size?: number;\n }>;\n const existingClass = element.props.className ?? '';\n const className = /\\bsize-|\\bw-|\\bh-/.test(existingClass)\n ? existingClass\n : `${existingClass} ds:size-4`.trim();\n return cloneElement(element, { className, size: element.props.size ?? 16 });\n}\n\n/* ------------------------------------------------------------------ */\n/* Context */\n/* ------------------------------------------------------------------ */\n\ninterface ToolbarContextValue {\n /** Accessor to the live AG Grid API. Returns `undefined` until mount. */\n getApi: () => GridApi | undefined;\n /** Number of rows currently selected (re-renders on selection change). */\n selectionCount: number;\n /** Trigger the browser print dialog for the grid. */\n onPrint: () => void;\n}\n\nconst ToolbarContext = createContext<ToolbarContextValue | null>(null);\n\nfunction useToolbarContext(caller: string): ToolbarContextValue {\n const ctx = useContext(ToolbarContext);\n if (!ctx) {\n throw new Error(\n `${caller} must be rendered inside <DataTable.Toolbar> as a descendant of <DataTable>.`,\n );\n }\n return ctx;\n}\n\nexport interface ToolbarProviderProps {\n getApi: () => GridApi | undefined;\n selectionCount: number;\n onPrint: () => void;\n children: ReactNode;\n}\n\nexport function ToolbarProvider({\n getApi,\n selectionCount,\n onPrint,\n children,\n}: ToolbarProviderProps) {\n const value = useMemo(\n () => ({ getApi, selectionCount, onPrint }),\n [getApi, selectionCount, onPrint],\n );\n return (\n <ToolbarContext.Provider value={value}>{children}</ToolbarContext.Provider>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Toolbar root */\n/* ------------------------------------------------------------------ */\n\nconst TOOLBAR_BASE = [\n 'data-table-toolbar',\n // Mobile (<sm) keeps `flex-wrap` so a wide QuickSearch can flow above the\n // Actions cluster on narrow screens. From `sm` (≥640px) we switch to\n // `flex-nowrap` + `min-w-0` so the row stays single-line at every common\n // desktop width (1024 / 1280 / 1440) — the QuickSearch slot shrinks via\n // its own `min-w-0` instead of pushing the trailing Actions to a new row.\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:sm:flex-nowrap ds:min-w-0',\n // Brand-polish: give the toolbar its own card surface so it doesn't\n // sit flush above the grid as a bare row. The `--card` token resolves to\n // `--background` on the default light theme (white), which makes a\n // shadow-only chrome invisible on the page — pair the card fill with the\n // standard `--card-border` outline (same recipe as `<Card>`) so the\n // toolbar reads as a discrete surface in both light and dark themes.\n 'ds:bg-[var(--card)] ds:rounded-[var(--radius-md)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:shadow-[var(--shadow-sm)]',\n 'ds:py-[var(--spacing-sm)] ds:px-[var(--spacing-md)]',\n].join(' ');\n\nexport type ToolbarRootProps = HTMLAttributes<HTMLDivElement>;\n\nconst ToolbarRoot = forwardRef<HTMLDivElement, ToolbarRootProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n role=\"toolbar\"\n className={[TOOLBAR_BASE, className ?? ''].join(' ').trim()}\n {...props}\n >\n {children}\n </div>\n ),\n);\nToolbarRoot.displayName = 'DataTable.Toolbar';\n\n/* ------------------------------------------------------------------ */\n/* FilterBar slot — free-form */\n/* ------------------------------------------------------------------ */\n\nconst FilterBar = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n // `grow` lets FilterBar absorb the free space; `min-w-0` lets the\n // QuickSearch slot inside shrink below its intrinsic width when the\n // toolbar runs `flex-nowrap` at `sm` and above, so the trailing\n // Actions cluster stays pinned on a single row.\n 'ds:grow ds:min-w-0',\n className ?? '',\n ]\n .join(' ')\n .trim()}\n {...props}\n >\n {children}\n </div>\n ),\n);\nFilterBar.displayName = 'DataTable.Toolbar.FilterBar';\n\n/* ------------------------------------------------------------------ */\n/* Actions slot — right-aligned via ms-auto */\n/* ------------------------------------------------------------------ */\n\nconst Actions = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:ms-auto',\n className ?? '',\n ]\n .join(' ')\n .trim()}\n {...props}\n >\n {children}\n </div>\n ),\n);\nActions.displayName = 'DataTable.Toolbar.Actions';\n\n/* ------------------------------------------------------------------ */\n/* ExportCsv, ExportPdf, Print — icon-only buttons with tooltip labels */\n/* ------------------------------------------------------------------ */\n/* These three share the same shape: a single lucide icon, a localized\n * tooltip that doubles as the accessible label, and either a built-in\n * action (CSV / print) or a consumer-supplied handler (PDF). Rendered\n * as IconButton so a toolbar with several of them reads as a compact\n * icon group rather than three full-width labeled buttons. */\n\ntype ToolbarIconButtonProps = Omit<\n IconButtonProps,\n 'icon' | 'aria-label' | 'tooltip' | 'onClick'\n> & {\n /** Accessible label — becomes the tooltip text and `aria-label`. */\n label?: string;\n};\n\nexport interface ExportCsvProps extends ToolbarIconButtonProps {\n /** Optional override — receives the live AG Grid API. */\n onExport?: (api: GridApi) => void;\n}\n\nconst ExportCsv = forwardRef<HTMLButtonElement, ExportCsvProps>(\n ({ label, onExport, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ExportCsv');\n const handleClick = useCallback(() => {\n const api = getApi();\n if (!api) return;\n if (onExport) onExport(api);\n else api.exportDataAsCsv();\n }, [getApi, onExport]);\n\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<Download aria-hidden />}\n tooltip={label ?? t('dataTable.exportCsv')}\n onClick={handleClick}\n {...rest}\n />\n );\n },\n);\nExportCsv.displayName = 'DataTable.Toolbar.ExportCsv';\n\nexport interface ExportPdfProps extends ToolbarIconButtonProps {\n /**\n * Optional override for the default PDF generation. When omitted, clicking\n * the button calls the built-in handler (`defaultExportPdf`) which\n * dynamic-imports `jspdf` + `jspdf-autotable` and produces a paged PDF\n * of the current sort/filter state. Supply your own to plug in a\n * server-side PDF generator or a custom layout.\n */\n onClick?: (api: GridApi | undefined) => void;\n /** Filename for the generated PDF (default `data-table-export.pdf`). */\n fileName?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Default PDF handler — dynamic-imported so jspdf doesn't ship in */\n/* main bundle unless the user clicks Export PDF */\n/* ------------------------------------------------------------------ */\n\n// Resolve a DS HSL token to an `[r, g, b]` tuple by letting the browser do\n// the work. `--card` etc. are stored as raw `H S% L%` triplets — wrap in\n// `hsl(...)` and read back from a temp element's computed color. The\n// imperative `.style.*` mutation here is on a transient probe element\n// (never attached to JSX), permitted per src/docs/23-constraints.mdx\n// §Runtime-computed dimensions.\nfunction resolveTokenToRgb(\n varName: string,\n fallback: [number, number, number] = [30, 30, 30],\n): [number, number, number] {\n // SSR or unparseable computed color: return a neutral foreground RGB by\n // default so the PDF is at least legible — `[255, 255, 255]` would\n // produce white-on-white. Callers can override per-token (e.g. fill\n // tokens pass a light fallback, text tokens pass a dark one).\n if (typeof document === 'undefined') return fallback;\n const probe = document.createElement('span');\n probe.style.color = `hsl(var(${varName}))`;\n probe.style.position = 'absolute';\n probe.style.visibility = 'hidden';\n document.body.appendChild(probe);\n const computed = getComputedStyle(probe).color;\n document.body.removeChild(probe);\n const match = computed.match(/rgba?\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)/i);\n if (!match) return fallback;\n return [Number(match[1]), Number(match[2]), Number(match[3])];\n}\n\ninterface DefaultExportPdfOptions {\n fileName: string;\n}\n\n/**\n * Default Export PDF handler. Exported for tests and for consumers who want\n * to call it from a custom `onClick` (e.g. to add a logo or signature).\n */\nexport async function defaultExportPdf(\n api: GridApi | undefined,\n options: DefaultExportPdfOptions,\n): Promise<void> {\n if (!api) return;\n // Dynamic-imported so jspdf + jspdf-autotable stay out of consumers'\n // main bundles unless the user actually clicks Export PDF.\n const [{ jsPDF }, { default: autoTable }] = await Promise.all([\n import('jspdf'),\n import('jspdf-autotable'),\n ]);\n\n const columns = api.getColumns() ?? [];\n const visibleColumns = columns.filter((col) => col.isVisible());\n\n const head = [\n visibleColumns.map((col) => api.getDisplayNameForColumn(col, null) ?? ''),\n ];\n\n // Pull rows in current sort + filter order. AG Grid Community supports\n // forEachNodeAfterFilterAndSort on the client-side row model — the only\n // model this wrapper exposes.\n const body: string[][] = [];\n api.forEachNodeAfterFilterAndSort((node) => {\n if (!node.data) return;\n const cells = visibleColumns.map((col) => {\n const value = api.getCellValue({\n rowNode: node,\n colKey: col,\n useFormatter: true,\n });\n return value == null ? '' : String(value);\n });\n body.push(cells);\n });\n\n // Map DS tokens → RGB at handler runtime. `--card` backs the cell\n // background; `--muted` backs the header fill; `--card-foreground`\n // backs the body text and `--foreground` the header text. Per-token\n // fallbacks default fill tokens to a light grey and text tokens to a\n // dark grey, so SSR / token-resolution failure still produces a\n // legible PDF rather than white-on-white.\n const headerFill = resolveTokenToRgb('--muted', [240, 240, 240]);\n const headerText = resolveTokenToRgb('--foreground', [30, 30, 30]);\n const bodyText = resolveTokenToRgb('--card-foreground', [30, 30, 30]);\n const alternateFill = resolveTokenToRgb('--card', [250, 250, 250]);\n\n const doc = new jsPDF({ orientation: 'landscape' });\n autoTable(doc, {\n head,\n body,\n headStyles: { fillColor: headerFill, textColor: headerText },\n bodyStyles: { textColor: bodyText },\n alternateRowStyles: { fillColor: alternateFill },\n styles: {\n font: 'helvetica',\n fontSize: 10,\n cellPadding: 4,\n },\n });\n doc.save(options.fileName);\n}\n\nconst ExportPdf = forwardRef<HTMLButtonElement, ExportPdfProps>(\n ({ label, onClick, fileName, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ExportPdf');\n const handleClick = useCallback(() => {\n const api = getApi();\n if (onClick) {\n onClick(api);\n return;\n }\n // Fire-and-forget — errors bubble to the console for now; consumers\n // who need to surface them should supply their own `onClick`.\n void defaultExportPdf(api, {\n fileName: fileName ?? 'data-table-export.pdf',\n });\n }, [getApi, onClick, fileName]);\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<FileText aria-hidden />}\n tooltip={label ?? t('dataTable.exportPdf')}\n onClick={handleClick}\n {...rest}\n />\n );\n },\n);\nExportPdf.displayName = 'DataTable.Toolbar.ExportPdf';\n\nexport type PrintProps = ToolbarIconButtonProps;\n\nconst Print = forwardRef<HTMLButtonElement, PrintProps>(\n ({ label, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n const { onPrint } = useToolbarContext('DataTable.Toolbar.Print');\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<Printer aria-hidden />}\n tooltip={label ?? t('dataTable.print')}\n onClick={onPrint}\n {...rest}\n />\n );\n },\n);\nPrint.displayName = 'DataTable.Toolbar.Print';\n\n/* ------------------------------------------------------------------ */\n/* QuickSearch — `<TextInput size=\"sm\">` wired to AG Grid quickFilterText */\n/* ------------------------------------------------------------------ */\n\nexport interface QuickSearchProps {\n /** Placeholder text. Falls back to `t('dataTable.quickSearch.placeholder')`. */\n placeholder?: string;\n /** Debounce ms before pushing to AG Grid. Defaults to 150 ms. */\n debounceMs?: number;\n}\n\nconst QuickSearch = ({ placeholder, debounceMs = 150 }: QuickSearchProps) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.QuickSearch');\n const [value, setValue] = useState('');\n const timerRef = useRef<number | undefined>(undefined);\n\n useEffect(() => {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n timerRef.current = window.setTimeout(() => {\n const api = getApi();\n if (!api) return;\n // `setGridOption` is the public path in AG Grid v33+ for changing\n // any grid option after init.\n api.setGridOption('quickFilterText', value);\n }, debounceMs);\n return () => {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n };\n }, [value, debounceMs, getApi]);\n\n return (\n // Slot wrapper caps the search at a sensible legible width on desktop —\n // without this, TextInput's `w-full` lets the QuickSearch absorb the\n // entire FilterBar row and push trailing Actions onto a second line at\n // 1024 / 1280 / 1440. `min-w-0` lets the slot shrink below `24rem` when\n // the toolbar is squeezed on narrow viewports. There is no\n // `--toolbar-search-max` token in the kit yet — see this component's\n // summary for a follow-up note recommending we add one.\n <div className=\"ds:w-full ds:max-w-[24rem] ds:min-w-0\">\n <TextInput\n type=\"search\"\n size=\"sm\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder={\n placeholder ?? t('dataTable.quickSearch.placeholder', 'Search…')\n }\n startAdornment={<Search aria-hidden className=\"ds:size-4\" />}\n clearable\n onClear={() => setValue('')}\n aria-label={t('dataTable.quickSearch.label', 'Quick search')}\n />\n </div>\n );\n};\nQuickSearch.displayName = 'DataTable.Toolbar.QuickSearch';\n\n/* ------------------------------------------------------------------ */\n/* Refresh — IconButton with a refresh glyph */\n/* ------------------------------------------------------------------ */\n\nexport interface RefreshButtonProps extends Omit<\n IconButtonProps,\n 'icon' | 'aria-label' | 'tooltip' | 'onClick'\n> {\n /** Called when the user clicks Refresh. */\n onRefresh: () => void;\n /** Accessible label. Falls back to `t('dataTable.refresh')`. */\n label?: string;\n}\n\nconst Refresh = forwardRef<HTMLButtonElement, RefreshButtonProps>(\n ({ onRefresh, label, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<RefreshCw aria-hidden />}\n tooltip={label ?? t('dataTable.refresh', 'Refresh')}\n onClick={onRefresh}\n {...rest}\n />\n );\n },\n);\nRefresh.displayName = 'DataTable.Toolbar.Refresh';\n\n/* ------------------------------------------------------------------ */\n/* FilterChips — chips for every active filter + clear-all */\n/* ------------------------------------------------------------------ */\n\ninterface ActiveFilterChip {\n colId: string;\n headerName: string;\n text: string;\n}\n\nfunction describeFilterModel(model: unknown): string {\n if (!model || typeof model !== 'object') return '';\n const m = model as Record<string, unknown>;\n // Text filter shape: { type, filter, filterTo, filterType }\n if (typeof m.filter === 'string' || typeof m.filter === 'number') {\n const type = typeof m.type === 'string' ? m.type : '';\n const filterTo =\n typeof m.filterTo === 'string' || typeof m.filterTo === 'number'\n ? String(m.filterTo)\n : '';\n if (type === 'inRange' && filterTo) {\n return `${m.filter} – ${filterTo}`;\n }\n return type ? `${type} ${m.filter}` : String(m.filter);\n }\n // Date filter shape: { type, dateFrom, dateTo }\n if (typeof m.dateFrom === 'string') {\n if (typeof m.dateTo === 'string' && m.dateTo) {\n return `${m.dateFrom} – ${m.dateTo}`;\n }\n return String(m.dateFrom);\n }\n // Set filter shape: { values: [...] }\n if (Array.isArray((m as { values?: unknown[] }).values)) {\n const values = (m as { values: unknown[] }).values;\n return values.map(String).join(', ');\n }\n return '';\n}\n\nconst FilterChips = () => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.FilterChips');\n const [chips, setChips] = useState<ActiveFilterChip[]>([]);\n const [quickFilter, setQuickFilter] = useState<string>('');\n\n const refresh = useCallback(() => {\n const api = getApi();\n if (!api) {\n setChips([]);\n setQuickFilter('');\n return;\n }\n const model = api.getFilterModel() ?? {};\n const cols = api.getColumns() ?? [];\n const next: ActiveFilterChip[] = [];\n for (const colId of Object.keys(model)) {\n const col = cols.find((c) => c.getColId() === colId);\n const headerName = api.getDisplayNameForColumn(col!, null) ?? colId;\n next.push({\n colId,\n headerName,\n text: describeFilterModel(model[colId]),\n });\n }\n setChips(next);\n const qf = api.getGridOption('quickFilterText');\n setQuickFilter(typeof qf === 'string' ? qf : '');\n }, [getApi]);\n\n // Subscribe to AG Grid filter-changed events. Use `addEventListener`\n // for the public subscription path (v33+ keeps this stable).\n useEffect(() => {\n const api = getApi();\n if (!api) return;\n const handler = (_event: FilterChangedEvent) => refresh();\n api.addEventListener('filterChanged', handler);\n refresh();\n return () => {\n api.removeEventListener('filterChanged', handler);\n };\n }, [getApi, refresh]);\n\n const total = chips.length + (quickFilter ? 1 : 0);\n if (total === 0) return null;\n\n function clearOne(colId: string) {\n const api = getApi();\n if (!api) return;\n api.destroyFilter(colId);\n }\n\n function clearAll() {\n const api = getApi();\n if (!api) return;\n api.setFilterModel(null);\n api.setGridOption('quickFilterText', '');\n setQuickFilter('');\n }\n\n return (\n <div\n role=\"group\"\n aria-label={t('dataTable.filterChips.label', 'Active filters')}\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {quickFilter && (\n <Tag\n label={`${t('dataTable.quickSearch.label', 'Quick search')}: ${quickFilter}`}\n size=\"sm\"\n fill=\"outline\"\n onRemove={() => {\n const api = getApi();\n api?.setGridOption('quickFilterText', '');\n setQuickFilter('');\n }}\n />\n )}\n {chips.map((c) => (\n <Tag\n key={c.colId}\n label={c.text ? `${c.headerName}: ${c.text}` : c.headerName}\n size=\"sm\"\n fill=\"outline\"\n onRemove={() => clearOne(c.colId)}\n />\n ))}\n <Button\n type=\"button\"\n intent=\"ghost\"\n size=\"sm\"\n onClick={clearAll}\n startIcon={<X aria-hidden className=\"ds:size-4\" />}\n >\n {t('dataTable.filterChips.clearAll', 'Clear all')}\n </Button>\n </div>\n );\n};\nFilterChips.displayName = 'DataTable.Toolbar.FilterChips';\n\n/* ------------------------------------------------------------------ */\n/* FacetFilter — pill-row column-scoped filter */\n/* ------------------------------------------------------------------ */\n\nexport interface FacetFilterOption<TValue = string> {\n value: TValue | null;\n label: string;\n}\n\nexport interface FacetFilterProps<TValue = string> {\n /** Column field to filter on. */\n field: string;\n /** Options shown as pills. `value: null` clears the filter. */\n options: FacetFilterOption<TValue>[];\n /** Accessible label for the pill group. */\n label?: string;\n}\n\nconst FacetFilter = <TValue extends string | number | boolean = string>({\n field,\n options,\n label,\n}: FacetFilterProps<TValue>) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.FacetFilter');\n const [active, setActive] = useState<TValue | null>(null);\n\n function apply(value: TValue | null) {\n setActive(value);\n const api = getApi();\n if (!api) return;\n if (value === null) {\n api.destroyFilter(field);\n return;\n }\n // Use the column filter API directly — AG Grid Community supports\n // setColumnFilterModel for the built-in filter on a column.\n api.setColumnFilterModel(field, {\n type: 'equals',\n filter: value,\n });\n api.onFilterChanged();\n }\n\n return (\n <div\n role=\"group\"\n aria-label={label ?? t('dataTable.facetFilter.label', 'Filter')}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {options.map((opt) => {\n const isActive = active === opt.value;\n return (\n <Button\n key={String(opt.value)}\n type=\"button\"\n size=\"sm\"\n intent={isActive ? 'primary' : 'secondary'}\n aria-pressed={isActive}\n onClick={() => apply(opt.value)}\n >\n {opt.label}\n </Button>\n );\n })}\n </div>\n );\n};\n(FacetFilter as { displayName?: string }).displayName =\n 'DataTable.Toolbar.FacetFilter';\n\n/* ------------------------------------------------------------------ */\n/* ExportMenu — compound: CSV (always), Excel (xlsx), PDF, custom */\n/* ------------------------------------------------------------------ */\n\nexport type ExportFormat = 'csv' | 'xlsx' | 'pdf' | 'custom';\n\nexport interface ExportMenuItemProps {\n /** Built-in format or `custom` for consumer-supplied handler. */\n format: ExportFormat;\n /** Label override. Built-in formats default to `t('dataTable.export.{format}')`. */\n label?: string;\n /** Consumer handler — required for `format: 'custom'`. */\n onClick?: (api: GridApi | undefined) => void;\n /** File-name override (only used by built-in formats). */\n fileName?: string;\n}\n\nconst DEFAULT_EXPORT_ITEMS: ExportFormat[] = ['csv', 'xlsx', 'pdf'];\n\nasync function defaultExportXlsx(\n api: GridApi | undefined,\n options: { fileName: string },\n): Promise<void> {\n if (!api) return;\n // Dynamic-imported so exceljs stays out of consumers' main bundles\n // unless the user actually clicks Excel export.\n const ExcelJS = await import('exceljs');\n const workbook = new ExcelJS.Workbook();\n const sheet = workbook.addWorksheet('Sheet1');\n\n const columns = api.getColumns() ?? [];\n const visibleColumns = columns.filter((col) => col.isVisible());\n\n sheet.addRow(\n visibleColumns.map(\n (col) => api.getDisplayNameForColumn(col, null) ?? col.getColId(),\n ),\n );\n\n api.forEachNodeAfterFilterAndSort((node) => {\n if (!node.data) return;\n sheet.addRow(\n visibleColumns.map((col) => {\n const value = api.getCellValue({\n rowNode: node,\n colKey: col,\n useFormatter: true,\n });\n return value == null ? '' : value;\n }),\n );\n });\n\n // Header row uses DS tokens resolved at runtime — same approach as\n // defaultExportPdf above.\n const headerFill = resolveTokenToRgb('--muted', [240, 240, 240]);\n const headerText = resolveTokenToRgb('--foreground', [30, 30, 30]);\n const headerRow = sheet.getRow(1);\n const hex = ([r, g, b]: [number, number, number]) =>\n `${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b\n .toString(16)\n .padStart(2, '0')}`.toUpperCase();\n headerRow.eachCell((cell: import('exceljs').Cell) => {\n cell.font = { bold: true, color: { argb: `FF${hex(headerText)}` } };\n cell.fill = {\n type: 'pattern',\n pattern: 'solid',\n fgColor: { argb: `FF${hex(headerFill)}` },\n };\n });\n\n const buffer = await workbook.xlsx.writeBuffer();\n const blob = new Blob([buffer], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = options.fileName;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\ninterface ExportMenuContextValue {\n /** AG Grid API resolver (forwarded to each item). */\n getApi: () => GridApi | undefined;\n}\n\nconst ExportMenuContext = createContext<ExportMenuContextValue | null>(null);\n\nfunction useExportMenuContext(): ExportMenuContextValue {\n const ctx = useContext(ExportMenuContext);\n if (!ctx) {\n throw new Error(\n 'DataTable.Toolbar.ExportMenu.Item must be rendered inside DataTable.Toolbar.ExportMenu.',\n );\n }\n return ctx;\n}\n\nexport interface ExportMenuProps {\n /** Custom menu items. When omitted, renders the default CSV+Excel+PDF trio. */\n children?: ReactNode;\n /** Accessible label for the trigger. */\n label?: string;\n}\n\nconst ExportMenu = ({ children, label }: ExportMenuProps) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ExportMenu');\n const value = useMemo(() => ({ getApi }), [getApi]);\n const itemsContent =\n children ??\n DEFAULT_EXPORT_ITEMS.map((f) => <ExportMenuItem key={f} format={f} />);\n return (\n <ExportMenuContext.Provider value={value}>\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <IconButton\n type=\"button\"\n intent=\"outline\"\n icon={<Download aria-hidden />}\n tooltip={label ?? t('dataTable.export.menu', 'Export')}\n aria-label={label ?? t('dataTable.export.menu', 'Export')}\n aria-haspopup=\"menu\"\n />\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\" sideOffset={4}>\n {itemsContent}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </ExportMenuContext.Provider>\n );\n};\nExportMenu.displayName = 'DataTable.Toolbar.ExportMenu';\n\nfunction defaultLabel(\n t: (key: string, fallback: string) => string,\n format: ExportFormat,\n): string {\n if (format === 'csv') return t('dataTable.export.csv', 'Export CSV');\n if (format === 'xlsx') return t('dataTable.export.xlsx', 'Export Excel');\n if (format === 'pdf') return t('dataTable.export.pdf', 'Export PDF');\n return t('dataTable.export.custom', 'Export');\n}\n\nfunction defaultIcon(format: ExportFormat): ReactNode {\n if (format === 'csv') return <Download aria-hidden className=\"ds:size-4\" />;\n if (format === 'xlsx')\n return <FileSpreadsheet aria-hidden className=\"ds:size-4\" />;\n if (format === 'pdf') return <FileText aria-hidden className=\"ds:size-4\" />;\n return <Download aria-hidden className=\"ds:size-4\" />;\n}\n\nconst ExportMenuItem = ({\n format,\n label,\n onClick,\n fileName,\n}: ExportMenuItemProps) => {\n const { t } = useTranslation();\n const { getApi } = useExportMenuContext();\n const handleClick = useCallback(() => {\n const api = getApi();\n if (format === 'csv') {\n api?.exportDataAsCsv();\n return;\n }\n if (format === 'pdf') {\n void defaultExportPdf(api, {\n fileName: fileName ?? 'data-table-export.pdf',\n });\n return;\n }\n if (format === 'xlsx') {\n void defaultExportXlsx(api, {\n fileName: fileName ?? 'data-table-export.xlsx',\n });\n return;\n }\n // custom — consumer is required to handle.\n onClick?.(api);\n }, [format, fileName, onClick, getApi]);\n\n return (\n <DropdownMenu.Item onSelect={handleClick}>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n {defaultIcon(format)}\n <span>{label ?? defaultLabel(t, format)}</span>\n </span>\n </DropdownMenu.Item>\n );\n};\nExportMenuItem.displayName = 'DataTable.Toolbar.ExportMenu.Item';\n\n/* ------------------------------------------------------------------ */\n/* ColumnToggle — popover with a checkbox per column */\n/* ------------------------------------------------------------------ */\n\ninterface ColumnEntry {\n colId: string;\n displayName: string;\n visible: boolean;\n}\n\nfunction readColumnEntries(api: GridApi | undefined): ColumnEntry[] {\n if (!api) return [];\n const columns = api.getColumns() ?? [];\n return columns\n .map((col) => {\n const def = col.getColDef();\n if (def.hide === undefined && col.getColId().startsWith('ag-Grid-'))\n return null;\n return {\n colId: col.getColId(),\n displayName: api.getDisplayNameForColumn(col, null) || col.getColId(),\n visible: col.isVisible(),\n };\n })\n .filter((c): c is ColumnEntry => c !== null);\n}\n\nexport interface ColumnToggleProps {\n label?: string;\n}\n\nconst ColumnToggle = ({ label }: ColumnToggleProps) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ColumnToggle');\n const [open, setOpen] = useState(false);\n const [columns, setColumns] = useState<ColumnEntry[]>([]);\n const [draggingColId, setDraggingColId] = useState<string | null>(null);\n const [dragOverColId, setDragOverColId] = useState<string | null>(null);\n\n // Refresh the column list whenever the popover opens — picks up\n // columns that were added/removed/renamed since last open.\n useEffect(() => {\n if (!open) return;\n setColumns(readColumnEntries(getApi()));\n }, [open, getApi]);\n\n const toggleColumn = useCallback(\n (colId: string, nextVisible: boolean) => {\n const api = getApi();\n if (!api) return;\n api.setColumnsVisible([colId], nextVisible);\n setColumns((prev) =>\n prev.map((c) =>\n c.colId === colId ? { ...c, visible: nextVisible } : c,\n ),\n );\n },\n [getApi],\n );\n\n // Reorder local list AND forward the move to AG Grid so the grid's\n // column order tracks the popover. `api.moveColumns([id], toIndex)`\n // does both the data move and the display refresh in v33+.\n const moveColumn = useCallback(\n (fromColId: string, toColId: string) => {\n if (fromColId === toColId) return;\n const api = getApi();\n if (!api) return;\n setColumns((prev) => {\n const fromIdx = prev.findIndex((c) => c.colId === fromColId);\n const toIdx = prev.findIndex((c) => c.colId === toColId);\n if (fromIdx < 0 || toIdx < 0) return prev;\n const next = [...prev];\n const [moved] = next.splice(fromIdx, 1);\n next.splice(toIdx, 0, moved);\n return next;\n });\n const toIdx = columns.findIndex((c) => c.colId === toColId);\n if (toIdx >= 0) api.moveColumns([fromColId], toIdx);\n },\n [getApi, columns],\n );\n\n const labelText = label ?? t('dataTable.columnToggle');\n\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>\n <IconButton\n type=\"button\"\n intent=\"outline\"\n icon={<Columns aria-hidden />}\n aria-label={labelText}\n aria-haspopup=\"dialog\"\n />\n </Popover.Trigger>\n <Popover.Content size=\"sm\" align=\"end\">\n <Popover.Heading>{labelText}</Popover.Heading>\n <ul\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n aria-label={labelText}\n >\n {columns.map((c) => {\n const isDragging = draggingColId === c.colId;\n const isDragOver =\n dragOverColId === c.colId && draggingColId !== c.colId;\n return (\n <li\n key={c.colId}\n draggable\n onDragStart={(e) => {\n setDraggingColId(c.colId);\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', c.colId);\n }}\n onDragOver={(e) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setDragOverColId(c.colId);\n }}\n onDragLeave={() => {\n setDragOverColId((prev) => (prev === c.colId ? null : prev));\n }}\n onDrop={(e) => {\n e.preventDefault();\n const fromColId = e.dataTransfer.getData('text/plain');\n if (fromColId) moveColumn(fromColId, c.colId);\n setDraggingColId(null);\n setDragOverColId(null);\n }}\n onDragEnd={() => {\n setDraggingColId(null);\n setDragOverColId(null);\n }}\n className={[\n 'ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs,var(--spacing-xs))] ds:transition-colors',\n isDragging ? 'ds:opacity-50' : '',\n isDragOver\n ? 'ds:bg-[color:color-mix(in_srgb,var(--primary)_8%,transparent)]'\n : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:cursor-grab ds:text-[color:var(--muted-foreground)] ds:active:cursor-grabbing\"\n >\n <GripVertical className=\"ds:size-4\" />\n </span>\n <Checkbox\n label={c.displayName}\n checked={c.visible}\n onCheckedChange={(checked) =>\n toggleColumn(c.colId, checked === true)\n }\n />\n </li>\n );\n })}\n </ul>\n </Popover.Content>\n </Popover.Root>\n );\n};\nColumnToggle.displayName = 'DataTable.Toolbar.ColumnToggle';\n\n/* ------------------------------------------------------------------ */\n/* BulkAction — hidden when no rows are selected */\n/* ------------------------------------------------------------------ */\n\nexport interface BulkActionProps extends Omit<\n ButtonProps,\n 'onClick' | 'children' | 'startIcon' | 'intent'\n> {\n label: string;\n icon?: ReactNode;\n onClick: (api: GridApi | undefined) => void;\n variant?: 'default' | 'destructive';\n}\n\nconst BulkAction = forwardRef<HTMLButtonElement, BulkActionProps>(\n (\n { label, icon, onClick, variant = 'default', size = 'sm', ...rest },\n ref,\n ) => {\n const { t } = useTranslation();\n const { getApi, selectionCount } = useToolbarContext(\n 'DataTable.Toolbar.BulkAction',\n );\n if (selectionCount === 0) return null;\n\n const resolvedIntent =\n variant === 'destructive' ? 'destructive' : 'secondary';\n\n return (\n <Button\n ref={ref}\n type=\"button\"\n intent={resolvedIntent}\n size={size}\n startIcon={sizeIcon(icon)}\n onClick={() => onClick(getApi())}\n aria-label={`${label} (${t('dataTable.bulkAction', { count: selectionCount })})`}\n {...rest}\n >\n <span>{label}</span>\n <span\n aria-hidden=\"true\"\n className=\"ds:ms-[var(--spacing-xs)] ds:opacity-80\"\n >\n {t('dataTable.bulkAction', { count: selectionCount })}\n </span>\n </Button>\n );\n },\n);\nBulkAction.displayName = 'DataTable.Toolbar.BulkAction';\n\n/* ------------------------------------------------------------------ */\n/* Assembled namespace — mounted on DataTable.Toolbar downstream */\n/* ------------------------------------------------------------------ */\n\nconst ExportMenuNamespace = Object.assign(ExportMenu, {\n Item: ExportMenuItem,\n});\n\nexport const Toolbar = Object.assign(ToolbarRoot, {\n FilterBar,\n Actions,\n /** @deprecated Use `Toolbar.ExportMenu` with a `csv` item. */\n ExportCsv,\n /** @deprecated Use `Toolbar.ExportMenu` with a `pdf` item. */\n ExportPdf,\n Print,\n ColumnToggle,\n BulkAction,\n QuickSearch,\n Refresh,\n FilterChips,\n FacetFilter,\n ExportMenu: ExportMenuNamespace,\n});\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport i18next from 'i18next';\nimport { Search, X } from 'lucide-react';\nimport { TextInput } from '../../text-input';\nimport { Select, type SelectOption } from '../../select';\nimport { Button } from '../../button';\n\n/**\n * Custom AG Grid filter component — text-comparison filter.\n *\n * Fills the gap left by `agTextColumnFilter`'s stock browser-skinned\n * input by wrapping the kit's `<TextInput>` and `<Select>` so the\n * column-header menu (`TextFilter`) and the inline floating row\n * (`TextFloatingFilter`) match the DS form language.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'description',\n * filter: TextFilter,\n * floatingFilter: true,\n * floatingFilterComponent: TextFloatingFilter,\n * filterParams: { defaultOperator: 'contains' },\n * }\n * ```\n *\n * Model shape `{ type, filter }` mirrors AG Grid's `agTextColumnFilter`\n * text-operator vocabulary (`contains`, `equals`, `startsWith`,\n * `endsWith`, `notContains`) so server-side adapters that already\n * understand the stock filter can read this one identically.\n */\n\nexport type TextFilterOperator =\n | 'contains'\n | 'equals'\n | 'startsWith'\n | 'endsWith'\n | 'notContains';\n\nexport interface TextFilterModel {\n type: TextFilterOperator;\n filter: string;\n}\n\nexport interface TextFilterParams {\n placeholder?: string;\n defaultOperator?: TextFilterOperator;\n}\n\nconst OPERATORS: TextFilterOperator[] = [\n 'contains',\n 'equals',\n 'startsWith',\n 'endsWith',\n 'notContains',\n];\n\n// Accent-folded, case-insensitive comparison. Intl.Collator handles\n// locale-aware diacritic stripping (e.g. \"città\" ~ \"citta\") so users\n// don't need to type accented characters exactly to find rows.\nfunction makeMatcher(locale: string) {\n const collator = new Intl.Collator(locale, {\n sensitivity: 'base',\n usage: 'search',\n });\n\n // Intl.Collator.compare returns 0 only on full-string equality (under\n // sensitivity:base). For substring tests we slice and compare windows.\n function indexOf(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n if (needle.length > haystack.length) return -1;\n for (let i = 0; i <= haystack.length - needle.length; i += 1) {\n if (\n collator.compare(haystack.slice(i, i + needle.length), needle) === 0\n ) {\n return i;\n }\n }\n return -1;\n }\n\n return {\n equals: (a: string, b: string) => collator.compare(a, b) === 0,\n contains: (haystack: string, needle: string) =>\n indexOf(haystack, needle) !== -1,\n startsWith: (haystack: string, needle: string) =>\n needle.length <= haystack.length &&\n collator.compare(haystack.slice(0, needle.length), needle) === 0,\n endsWith: (haystack: string, needle: string) =>\n needle.length <= haystack.length &&\n collator.compare(\n haystack.slice(haystack.length - needle.length),\n needle,\n ) === 0,\n };\n}\n\nfunction coerceToString(raw: unknown): string | null {\n if (raw === null || raw === undefined) return null;\n return typeof raw === 'string' ? raw : String(raw);\n}\n\nexport function TextFilter(\n props: CustomFilterProps<unknown, unknown, TextFilterModel> &\n TextFilterParams,\n) {\n const { model, onModelChange, getValue, placeholder, defaultOperator } =\n props;\n const { t } = useTranslation('ui');\n\n const initialOperator: TextFilterOperator =\n model?.type ?? defaultOperator ?? 'contains';\n const [operator, setOperator] = useState<TextFilterOperator>(initialOperator);\n const [draft, setDraft] = useState<string>(model?.filter ?? '');\n\n // Hydrate local state when AG Grid pushes an external model change\n // (e.g. consumer calls api.setFilterModel programmatically).\n useEffect(() => {\n setOperator(model?.type ?? defaultOperator ?? 'contains');\n setDraft(model?.filter ?? '');\n }, [model, defaultOperator]);\n\n const matcher = useMemo(() => makeMatcher(i18next.language), []);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const active = model;\n if (!active || active.filter === '') return true;\n const value = coerceToString(getValue(params.node));\n if (value === null) return false;\n switch (active.type) {\n case 'equals':\n return matcher.equals(value, active.filter);\n case 'contains':\n return matcher.contains(value, active.filter);\n case 'startsWith':\n return matcher.startsWith(value, active.filter);\n case 'endsWith':\n return matcher.endsWith(value, active.filter);\n case 'notContains':\n return !matcher.contains(value, active.filter);\n default:\n return true;\n }\n },\n });\n\n function apply() {\n const trimmed = draft.trim();\n if (trimmed === '') {\n onModelChange(null);\n return;\n }\n onModelChange({ type: operator, filter: draft });\n }\n\n function clear() {\n setDraft('');\n setOperator(defaultOperator ?? 'contains');\n onModelChange(null);\n }\n\n const operatorOptions: SelectOption<TextFilterOperator>[] = OPERATORS.map(\n (op) => ({\n value: op,\n label: t(`dataTable.textFilter.operators.${op}`),\n }),\n );\n\n const placeholderLabel = placeholder ?? t('dataTable.textFilter.placeholder');\n\n return (\n <div\n data-component=\"text-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Select<TextFilterOperator>\n size=\"sm\"\n options={operatorOptions}\n value={operator}\n onValueChange={(next) => {\n if (next === '') return;\n setOperator(next);\n }}\n aria-label={t('dataTable.textFilter.operators.contains')}\n />\n <TextInput\n size=\"sm\"\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n apply();\n }\n }}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n startAdornment={<Search aria-hidden=\"true\" className=\"ds:size-4\" />}\n />\n <div className=\"ds:flex ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.textFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.textFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `TextFilter`.\n *\n * Renders a `<TextInput size=\"sm\">` directly as the inline floating\n * filter — leading search icon, optional trailing clear button, fixed\n * operator (the popover version owns operator selection so the inline\n * row stays compact).\n *\n * Commits debounce at 200ms; empty input commits `null` so the grid\n * stops filtering as soon as the field is blank.\n */\nexport function TextFloatingFilter(\n props: CustomFloatingFilterProps<IFilter, unknown, unknown, TextFilterModel>,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as TextFilterParams | undefined) ?? {};\n const defaultOperator: TextFilterOperator =\n filterParams.defaultOperator ?? 'contains';\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.textFilter.placeholder');\n\n const [draft, setDraft] = useState<string>(model?.filter ?? '');\n\n // Hydrate when the model changes externally (programmatic reset).\n useEffect(() => {\n setDraft(model?.filter ?? '');\n }, [model?.filter]);\n\n // Debounced commit. Avoids hammering AG Grid with a model push on\n // every keystroke; 200ms matches the kit's other deferred-input\n // patterns. A bare setTimeout + cleanup is sufficient — no third-party\n // debounce hook required.\n useEffect(() => {\n // Avoid spurious commits when the local draft already matches the\n // applied model (e.g. just-hydrated initial mount).\n if (draft === (model?.filter ?? '')) return;\n\n const timer = setTimeout(() => {\n if (draft === '') {\n if (model) onModelChange(null);\n return;\n }\n onModelChange({ type: defaultOperator, filter: draft });\n }, 200);\n\n return () => clearTimeout(timer);\n }, [draft, defaultOperator, model, onModelChange]);\n\n function clearImmediate() {\n setDraft('');\n if (model) onModelChange(null);\n }\n\n return (\n <div data-component=\"text-floating-filter\" className=\"ds:w-full\">\n <TextInput\n size=\"sm\"\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n startAdornment={<Search aria-hidden=\"true\" className=\"ds:size-4\" />}\n endAdornment={\n draft.length > 0 ? (\n <button\n type=\"button\"\n aria-label={t('dataTable.textFilter.clear')}\n onClick={clearImmediate}\n className=\"ds:pointer-events-auto ds:flex ds:items-center ds:text-[var(--muted-foreground)] ds:hover:text-[var(--foreground)] ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none\"\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n ) : undefined\n }\n />\n </div>\n );\n}\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — DataTable. */\n/* */\n/* Operations work against the curated `DataTableHandle`, never the raw */\n/* ag-grid `GridApi` (consumers needing the raw API call `getRawApi()`). */\n/* See `src/docs/26-agent-readiness.mdx` §15. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { DataTableHandle, DataTableSortEntry } from './data-table';\n\nexport const dataTableAgent: AgentAdapter<DataTableHandle> = {\n id: 'data-table',\n capabilities: [\n 'select_single',\n 'select_multiple',\n 'range_pick',\n 'filter',\n 'sort',\n 'paginate',\n ],\n state: {\n selection: {\n type: 'string[]',\n descriptionKey: 'ui.agent.dataTable.state.selection',\n description: 'Row ids of currently-selected rows.',\n read: (handle) => handle.getSelection(),\n },\n filter: {\n type: 'object',\n descriptionKey: 'ui.agent.dataTable.state.filter',\n description: 'Current ag-grid filter model, keyed by column id.',\n read: (handle) => handle.getFilter(),\n },\n sort: {\n type: 'Array<{ colId, sort }>',\n descriptionKey: 'ui.agent.dataTable.state.sort',\n description: 'Active sort, in priority order.',\n read: (handle) => handle.getSort(),\n },\n currentPage: {\n type: 'number',\n descriptionKey: 'ui.agent.dataTable.state.currentPage',\n description: 'Zero-indexed page number.',\n read: (handle) => handle.getCurrentPage(),\n },\n },\n actions: {\n select_rows: {\n safety: 'read',\n argsType: '{ ids: string[] }',\n descriptionKey: 'ui.agent.dataTable.actions.selectRows',\n description: 'Replace the current selection with the given row ids.',\n invoke: (handle, args: { ids: string[] }) => {\n handle.setSelection(args.ids);\n },\n },\n select_range: {\n safety: 'read',\n argsType: '{ fromId: string, toId: string }',\n descriptionKey: 'ui.agent.dataTable.actions.selectRange',\n description:\n 'Select every row between fromId and toId, inclusive, in current sort order.',\n invoke: (handle, args: { fromId: string; toId: string }) => {\n handle.selectRange(args.fromId, args.toId);\n },\n },\n clear_selection: {\n safety: 'read',\n descriptionKey: 'ui.agent.dataTable.actions.clearSelection',\n description: 'Deselect all rows.',\n invoke: (handle) => {\n handle.clearSelection();\n },\n },\n apply_filter: {\n safety: 'read',\n argsType: '{ model: Record<string, unknown> }',\n descriptionKey: 'ui.agent.dataTable.actions.applyFilter',\n description: 'Replace the filter model with the given object.',\n invoke: (handle, args: { model: Record<string, unknown> }) => {\n handle.setFilter(args.model);\n },\n },\n sort_by: {\n safety: 'read',\n argsType: '{ model: DataTableSortEntry[] }',\n descriptionKey: 'ui.agent.dataTable.actions.sortBy',\n description:\n 'Replace the active sort with the given list (priority order).',\n invoke: (handle, args: { model: DataTableSortEntry[] }) => {\n handle.setSort(args.model);\n },\n },\n go_to_page: {\n safety: 'read',\n argsType: '{ page: number }',\n descriptionKey: 'ui.agent.dataTable.actions.goToPage',\n description: 'Navigate to the given zero-indexed page.',\n invoke: (handle, args: { page: number }) => {\n handle.goToPage(args.page);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'data-table',\n description: 'Marks the DataTable wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'gridId',\n description:\n 'Sourced from the gridId prop. Required to address a specific table from the agent.',\n },\n item: {\n attr: 'row-id',\n description:\n 'Native ag-grid row-id attribute on each rendered row. Selection is performed via the curated handle, not by DOM mutation.',\n },\n },\n};\n","import 'ag-grid-community/styles/ag-grid.css';\n// Font-only — `@font-face { agGridQuartz }` for the icon glyphs. We\n// deliberately do NOT import `ag-theme-quartz.css`: that file scopes ~90\n// CSS variables to `.ag-theme-quartz` and hardcodes colors / IBM Plex Sans\n// / 8px grid, which fight the design-system tokens. `ag-grid-theme.css`\n// below is a standalone bridge that defines every var AG Grid references,\n// mapped to DS tokens.\nimport 'ag-grid-community/styles/agGridQuartzFont.css';\nimport '../../tokens/ag-grid-theme.css';\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode,\n} from 'react';\nimport { Skeleton } from '../skeleton';\nimport { EmptyState } from '../empty-state';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { AgGridReact } from 'ag-grid-react';\nimport {\n AllCommunityModule,\n ModuleRegistry,\n type ColDef,\n type ColGroupDef,\n type FilterChangedEvent,\n type GridApi,\n type GridOptions,\n type RowClassParams,\n type SortChangedEvent,\n} from 'ag-grid-community';\nimport { Toolbar, ToolbarProvider } from './toolbar';\nimport { TextFilter, TextFloatingFilter } from './filters/text-filter';\nimport { useAgentRegistration } from '../../agent';\nimport { usePrefersReducedMotion, useTheme } from '../../hooks';\nimport { dataTableAgent } from './data-table.agent';\n\n// AG Grid v33+ requires module registration before any grid renders.\nModuleRegistry.registerModules([AllCommunityModule]);\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst dataTableVariants = cva('ag-theme-alfadocs ds:w-full', {\n variants: {\n density: {\n default: '',\n compact: 'data-table-compact',\n expanded: 'data-table-expanded',\n },\n bordered: {\n true: '',\n false: 'ds:[--ag-borders:none]',\n },\n },\n defaultVariants: {\n density: 'default',\n bordered: true,\n },\n});\n\n/* ------------------------------------------------------------------ */\n/* Curated imperative handle — agent-readiness contract */\n/* ------------------------------------------------------------------ */\n\nexport interface DataTableSortEntry {\n colId: string;\n sort: 'asc' | 'desc';\n}\n\n/**\n * Curated handle exposed via `forwardRef`. Replaces the legacy raw `GridApi`\n * forwarding — see `src/docs/26-agent-readiness.mdx` §15. Consumers needing\n * the unwrapped ag-grid API call `getRawApi()`.\n */\nexport interface DataTableHandle<TData = unknown> {\n getSelection: () => string[];\n setSelection: (ids: string[]) => void;\n selectRange: (fromId: string, toId: string) => void;\n clearSelection: () => void;\n getFilter: () => Record<string, unknown>;\n setFilter: (model: Record<string, unknown>) => void;\n getSort: () => DataTableSortEntry[];\n setSort: (model: DataTableSortEntry[]) => void;\n getCurrentPage: () => number;\n goToPage: (page: number) => void;\n getRawApi: () => GridApi<TData> | undefined;\n}\n\n/* ------------------------------------------------------------------ */\n/* Props */\n/* ------------------------------------------------------------------ */\n\nexport interface DataTableProps<TData = unknown> extends Omit<\n VariantProps<typeof dataTableVariants>,\n 'density'\n> {\n /**\n * Column definitions — accepts a mix of leaf `ColDef`s and header\n * `ColGroupDef`s (for two-row grouped headers via `children: [...]`).\n */\n columnDefs: (ColDef<TData> | ColGroupDef<TData>)[];\n rowData?: TData[];\n rowSelection?: 'single' | 'multiple';\n pagination?: boolean;\n paginationPageSize?: number;\n /**\n * Page-size dropdown options shown in the AG Grid pagination panel.\n * Pass `false` to hide the dropdown entirely. Default: `[10, 25, 50, 100]`.\n */\n paginationPageSizeSelector?: number[] | false;\n gridId?: string;\n onSelectionChanged?: (rows: TData[]) => void;\n onSortChanged?: (event: SortChangedEvent<TData>) => void;\n onFilterChanged?: (event: FilterChangedEvent<TData>) => void;\n noRowsOverlay?: ComponentType;\n loadingOverlay?: ComponentType;\n gridOptions?: GridOptions<TData>;\n /** Grid height as a Tailwind height class, e.g. `\"h-[500px]\"` or `\"h-[var(--data-table-height)]\"` */\n heightClass?: string;\n className?: string;\n\n /** Row height preset. `expanded` adds headroom for complex cells (balances, tag lists). */\n density?: 'compact' | 'default' | 'expanded';\n\n /** Map row → class name. Use together with `data-table-row-success/warning/error` for tinted rows. */\n getRowClass?: (params: RowClassParams<TData>) => string | undefined;\n /** Rows pinned at the bottom of the grid. Use `useTotalRow()` to compute a totals row. */\n pinnedBottomRowData?: TData[];\n\n /** Print-optimised mode — hides toolbar, disables pagination, renders every row. */\n printMode?: boolean;\n\n /** Composable toolbar — renders `<DataTable.Toolbar>…</DataTable.Toolbar>` above the grid. */\n children?: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Locale text builder */\n/* ------------------------------------------------------------------ */\n\nfunction useAgLocaleText() {\n const { t } = useTranslation();\n return useMemo(\n () => ({\n // Filter strings\n contains: t('dataTable.agGrid.contains'),\n notContains: t('dataTable.agGrid.notContains'),\n equals: t('dataTable.agGrid.equals'),\n notEqual: t('dataTable.agGrid.notEqual'),\n startsWith: t('dataTable.agGrid.startsWith'),\n endsWith: t('dataTable.agGrid.endsWith'),\n lessThan: t('dataTable.agGrid.lessThan'),\n greaterThan: t('dataTable.agGrid.greaterThan'),\n inRange: t('dataTable.agGrid.inRange'),\n blank: t('dataTable.agGrid.blank'),\n notBlank: t('dataTable.agGrid.notBlank'),\n filterOoo: t('dataTable.agGrid.filterOoo'),\n applyFilter: t('dataTable.agGrid.applyFilter'),\n resetFilter: t('dataTable.agGrid.resetFilter'),\n noRowsToShow: t('dataTable.agGrid.noRowsToShow'),\n selectAll: t('dataTable.agGrid.selectAll'),\n // Pagination\n page: t('dataTable.page'),\n of: t('dataTable.of'),\n to: t('dataTable.to'),\n nextPage: t('dataTable.nextPage'),\n previousPage: t('dataTable.previousPage'),\n firstPage: t('dataTable.firstPage'),\n lastPage: t('dataTable.lastPage'),\n pageSize: t('dataTable.pageSize'),\n }),\n\n [t],\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Loading overlay */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultLoadingOverlay() {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:w-full ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)]\"\n >\n {Array.from({ length: 5 }).map((_, i) => (\n <Skeleton\n key={i}\n variant=\"rectangular\"\n className=\"ds:h-[var(--min-target-size)] ds:w-full\"\n />\n ))}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* No-rows overlay — wired to the DS EmptyState component */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultNoRowsOverlay() {\n const { t } = useTranslation();\n return (\n <EmptyState\n variant=\"no-results\"\n size=\"sm\"\n title={t('dataTable.noRows')}\n description={t('dataTable.noRowsDescription')}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Column persistence helpers */\n/* ------------------------------------------------------------------ */\n\nfunction loadColumnState(gridId: string) {\n try {\n const raw = localStorage.getItem(`data-table-col-state:${gridId}`);\n return raw ? JSON.parse(raw) : null;\n } catch {\n return null;\n }\n}\n\nfunction saveColumnState(gridId: string, api: GridApi) {\n try {\n localStorage.setItem(\n `data-table-col-state:${gridId}`,\n JSON.stringify(api.getColumnState()),\n );\n } catch {\n // localStorage may be unavailable in some environments\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* DataTable */\n/* ------------------------------------------------------------------ */\n\nfunction DataTableInner<TData = unknown>(\n props: DataTableProps<TData>,\n ref: React.ForwardedRef<DataTableHandle<TData>>,\n) {\n const {\n columnDefs,\n rowData,\n rowSelection,\n pagination = false,\n paginationPageSize = 25,\n paginationPageSizeSelector = [10, 25, 50, 100],\n gridId,\n onSelectionChanged,\n onSortChanged,\n onFilterChanged,\n noRowsOverlay,\n loadingOverlay,\n gridOptions,\n density,\n bordered,\n heightClass = 'ds:h-[500px]',\n className,\n getRowClass,\n pinnedBottomRowData,\n printMode = false,\n children,\n } = props;\n\n const { t, i18n } = useTranslation();\n const agGridRef = useRef<AgGridReact<TData>>(null);\n const [selectionCount, setSelectionCount] = useState(0);\n const [sortAnnouncement, setSortAnnouncement] = useState('');\n const localeText = useAgLocaleText();\n\n // Curated imperative handle — see DataTableHandle above.\n const handle = useMemo<DataTableHandle<TData>>(\n () => ({\n getSelection: () => {\n const api = agGridRef.current?.api;\n if (!api) return [];\n const ids: string[] = [];\n for (const node of api.getSelectedNodes()) {\n if (node.id != null) ids.push(node.id);\n }\n return ids;\n },\n setSelection: (ids) => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const want = new Set(ids);\n api.forEachNode((node) => {\n if (node.id != null) node.setSelected(want.has(node.id));\n });\n },\n selectRange: (fromId, toId) => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const ordered: string[] = [];\n api.forEachNodeAfterFilterAndSort((node) => {\n if (node.id != null) ordered.push(node.id);\n });\n const a = ordered.indexOf(fromId);\n const b = ordered.indexOf(toId);\n if (a < 0 || b < 0) return;\n const [lo, hi] = a <= b ? [a, b] : [b, a];\n const want = new Set(ordered.slice(lo, hi + 1));\n api.forEachNode((node) => {\n if (node.id != null) node.setSelected(want.has(node.id));\n });\n },\n clearSelection: () => {\n agGridRef.current?.api?.deselectAll();\n },\n getFilter: () => agGridRef.current?.api?.getFilterModel() ?? {},\n setFilter: (model) => {\n agGridRef.current?.api?.setFilterModel(model);\n },\n getSort: () => {\n const api = agGridRef.current?.api;\n if (!api) return [];\n return api\n .getColumnState()\n .filter((c) => c.sort === 'asc' || c.sort === 'desc')\n .map((c) => ({ colId: c.colId, sort: c.sort as 'asc' | 'desc' }));\n },\n setSort: (model) => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const next = api.getColumnState().map((c) => {\n const target = model.find((m) => m.colId === c.colId);\n return { ...c, sort: target ? target.sort : null };\n });\n api.applyColumnState({ state: next, defaultState: { sort: null } });\n },\n getCurrentPage: () =>\n agGridRef.current?.api?.paginationGetCurrentPage() ?? 0,\n goToPage: (page) => {\n agGridRef.current?.api?.paginationGoToPage(page);\n },\n getRawApi: () => agGridRef.current?.api,\n }),\n [],\n );\n\n useImperativeHandle(ref, () => handle, [handle]);\n // Agent adapter is keyed on the row-agnostic DataTableHandle; cast here\n // because TData isn't observable from the agent surface.\n useAgentRegistration(dataTableAgent, handle as DataTableHandle, gridId);\n\n const isRtl = i18n.dir() === 'rtl';\n const isLoading = rowData === undefined;\n\n // Reactive — re-renders when the OS preference or theme toggles mid-session.\n const prefersReducedMotion = usePrefersReducedMotion();\n const { resolvedTheme } = useTheme();\n // Suppress compact density in accessible theme — 32px rows violate min-target-size.\n const isAccessible =\n resolvedTheme === 'light-accessible' || resolvedTheme === 'dark-accessible';\n const effectiveDensity =\n isAccessible && density === 'compact' ? 'default' : density;\n\n // Map logical 'single' | 'multiple' → AG Grid v35 object form\n const rowSelectionOption = useMemo(() => {\n if (!rowSelection) return undefined;\n if (rowSelection === 'single') return { mode: 'singleRow' as const };\n return {\n mode: 'multiRow' as const,\n headerCheckbox: true,\n checkboxes: true,\n };\n }, [rowSelection]);\n\n // Column persistence — restore on mount\n const handleGridReady = useCallback(() => {\n if (!gridId || !agGridRef.current?.api) return;\n const saved = loadColumnState(gridId);\n if (saved) {\n agGridRef.current.api.applyColumnState({\n state: saved,\n applyOrder: true,\n });\n }\n }, [gridId]);\n\n const handleColumnStateChange = useCallback(() => {\n if (gridId && agGridRef.current?.api) {\n saveColumnState(gridId, agGridRef.current.api);\n }\n }, [gridId]);\n\n const handleSelectionChanged = useCallback(() => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const rows = api.getSelectedRows();\n setSelectionCount(rows.length);\n onSelectionChanged?.(rows);\n }, [onSelectionChanged]);\n\n const handleSortChanged = useCallback(\n (event: SortChangedEvent<TData>) => {\n const api = agGridRef.current?.api;\n if (api) {\n const colState = api.getColumnState();\n const sortedCol = colState.find((c) => c.sort);\n if (sortedCol) {\n const colId = sortedCol.colId;\n // Use the live AG Grid API so grouped headers and runtime column\n // mutations (visibility toggles, dynamic re-order) resolve correctly.\n const colDef = api.getColumnDef(colId);\n const colName = (colDef?.headerName as string) ?? colId;\n const dirKey =\n sortedCol.sort === 'asc'\n ? 'dataTable.sortAscending'\n : 'dataTable.sortDescending';\n setSortAnnouncement(\n t('dataTable.sortAnnounce', {\n column: colName,\n direction: t(dirKey),\n }),\n );\n } else {\n setSortAnnouncement('');\n }\n }\n onSortChanged?.(event);\n },\n [onSortChanged, t],\n );\n\n const handleFilterChanged = useCallback(\n (event: FilterChangedEvent<TData>) => {\n onFilterChanged?.(event);\n },\n [onFilterChanged],\n );\n\n // Clear sort announcement after screen readers have had time to read it\n useEffect(() => {\n if (!sortAnnouncement) return;\n const id = setTimeout(() => setSortAnnouncement(''), 3000);\n return () => clearTimeout(id);\n }, [sortAnnouncement]);\n\n const NoRowsComponent = noRowsOverlay ?? DefaultNoRowsOverlay;\n const LoadingComponent = loadingOverlay ?? DefaultLoadingOverlay;\n\n const getApi = useCallback(\n () => agGridRef.current?.api as GridApi | undefined,\n [],\n );\n\n const handlePrint = useCallback(() => {\n if (typeof window !== 'undefined') {\n window.print();\n }\n }, []);\n\n const wrapperClass = dataTableVariants({\n density: effectiveDensity,\n bordered,\n className,\n });\n\n // Toolbar composition — render either the consumer-provided children,\n // or a default ExportMenu (CSV + Excel + PDF) so every grid ships with\n // the full export trio for free. Excel + PDF are dynamic-imported by\n // their item handlers so they don't add weight to the main bundle.\n const toolbarContent = children ?? (\n <Toolbar>\n <Toolbar.Actions>\n <Toolbar.ExportMenu />\n </Toolbar.Actions>\n </Toolbar>\n );\n\n // Pagination is auto-disabled in print mode so every row prints.\n const paginationEnabled = printMode ? false : pagination;\n\n return (\n <div\n className=\"ds:flex ds:w-full ds:flex-col ds:gap-[var(--spacing-sm)]\"\n aria-busy={isLoading ? 'true' : undefined}\n data-component=\"data-table\"\n data-component-id={gridId}\n data-print-mode={printMode ? 'true' : undefined}\n >\n {!printMode && (\n <ToolbarProvider\n getApi={getApi}\n selectionCount={selectionCount}\n onPrint={handlePrint}\n >\n {toolbarContent}\n </ToolbarProvider>\n )}\n\n {/* Grid */}\n <div\n className={[wrapperClass, printMode ? '' : heightClass]\n .join(' ')\n .trim()}\n >\n <AgGridReact<TData>\n ref={agGridRef}\n // Opt into v32 CSS-file theming so the `.ag-theme-alfadocs` bridge\n // (src/tokens/ag-grid-theme.css) wins. Without this, AG Grid v33+\n // defaults to the JS Theming API (themeQuartz) which overrides our\n // tokens at runtime — including --ag-font-family.\n theme=\"legacy\"\n columnDefs={columnDefs}\n rowData={rowData}\n /* §11a — every column gets sort + filter + resize + floating\n filter by default. Consumers opt-out per column via\n `sortable: false` / `filter: false`. The spread at the end\n lets `gridOptions.defaultColDef` override individual keys\n without losing the rest.\n\n Note: the column-menu button (`menuTabs` /\n `suppressHeaderMenuButton`) requires `ColumnMenuModule`,\n which is Enterprise in v33+. The floating-filter row is the\n Community-friendly equivalent and covers the primary use\n case — sort + filter without an extra popup. */\n defaultColDef={{\n sortable: true,\n // Default filter = DS-styled text filter so untyped columns\n // (no explicit `filter:` override) inherit the kit's form\n // language instead of AG Grid's stock browser-skinned input.\n // Number / date / select columns opt into their dedicated\n // wrapper per-column.\n filter: TextFilter,\n floatingFilterComponent: TextFloatingFilter,\n resizable: true,\n floatingFilter: true,\n // §13d — faint sort icon advertises which columns are\n // sortable. v33+ moved this from grid-level to defaultColDef.\n unSortIcon: true,\n ...(gridOptions as GridOptions<TData> | undefined)?.defaultColDef,\n }}\n rowSelection={rowSelectionOption}\n pagination={paginationEnabled}\n paginationPageSize={paginationPageSize}\n paginationPageSizeSelector={paginationPageSizeSelector}\n /* §13k — locale-aware pagination chrome (\"1 a 25 di 1.287\" in\n Italian). AG Grid's default renders raw integers. */\n paginationNumberFormatter={(params) =>\n new Intl.NumberFormat(i18n.language).format(params.value)\n }\n animateRows={!prefersReducedMotion}\n enableRtl={isRtl}\n ensureDomOrder\n /* Enable CellSpanModule globally — gate prop required for any\n colDef using `spanRows: true` (Community). Zero runtime cost\n when no column opts in. */\n enableCellSpan\n /* §13a — selecting cell text with the mouse should just work\n (copy a patient ID, an invoice number). AG Grid defaults this\n to false; that breaks user expectation on web tables. */\n enableCellTextSelection\n /* §13b — when a user copies a range, include column headers in\n the clipboard so a paste into Excel/Sheets keeps context. */\n copyHeadersToClipboard\n /* §13c — locale-aware sort (Intl.Collator). \"à\" sorts next to\n \"a\", \"ñ\" next to \"n\". Italian-first matters. */\n accentedSort\n /* §13d unSortIcon — moved to defaultColDef above per v33+\n deprecation. */\n /* §13e — Ctrl/⌘ for multi-column sort. Accounting + clinical\n staff who live in these grids appreciate this. */\n multiSortKey=\"ctrl\"\n /* §13f — dragging a column header outside the grid no longer\n hides the column. Surprising default, easy to trigger by\n accident, hard to recover from without ColumnToggle. */\n suppressDragLeaveHidesColumns\n /* §13g — when row selection is enabled, require explicit\n checkbox/modifier-key selection. Don't fight the primary\n row action (open / edit / navigate) with click-anywhere\n selection. No-op when rowSelection is unset. */\n suppressRowClickSelection={rowSelection ? true : undefined}\n /* §13h — tooltip ergonomics: 500 ms show matches OS, 5 s hide\n gives time to read long content, hover keeps it visible. */\n tooltipShowDelay={500}\n tooltipHideDelay={5000}\n tooltipInteraction\n /* §13i — commit-on-blur contract for inline editing. No-op\n until any column declares `editable: true`. */\n stopEditingWhenCellsLoseFocus\n /* §13j — preserve user column reorder across columnDefs\n prop changes; pairs with the localStorage persistence below. */\n maintainColumnOrder\n /* §13l — Ctrl/⌘+Z for inline edits. No-op until editable\n columns appear. */\n undoRedoCellEditing\n undoRedoCellEditingLimit={20}\n suppressCellFocus={false}\n rowBuffer={10}\n localeText={localeText}\n noRowsOverlayComponent={NoRowsComponent}\n loadingOverlayComponent={LoadingComponent}\n getRowClass={getRowClass}\n pinnedBottomRowData={pinnedBottomRowData}\n domLayout={printMode ? 'autoHeight' : undefined}\n onGridReady={handleGridReady}\n onColumnMoved={handleColumnStateChange}\n onColumnResized={handleColumnStateChange}\n onColumnPinned={handleColumnStateChange}\n onSortChanged={handleSortChanged}\n onFilterChanged={handleFilterChanged}\n onSelectionChanged={handleSelectionChanged}\n {...(gridOptions as GridOptions<TData>)}\n />\n </div>\n\n {/* Footer */}\n {!printMode && (\n <div className=\"ds:flex ds:items-center ds:justify-between type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {selectionCount > 0 ? (\n <span>{t('dataTable.selected', { count: selectionCount })}</span>\n ) : (\n <span />\n )}\n </div>\n )}\n\n {/* Aria-live region for sort announcements */}\n <span role=\"status\" aria-live=\"polite\" className=\"ds:sr-only\">\n {sortAnnouncement}\n </span>\n </div>\n );\n}\n\nconst DataTableBase = forwardRef(DataTableInner) as <TData = unknown>(\n props: DataTableProps<TData> & { ref?: React.Ref<DataTableHandle<TData>> },\n) => React.ReactElement;\n\n(DataTableBase as { displayName?: string }).displayName = 'DataTable';\n\nexport const DataTable = Object.assign(DataTableBase, {\n Toolbar,\n});\n","import { useMemo } from 'react';\n\n/**\n * Compute a pinned total row from a dataset and a list of numeric fields.\n *\n * The returned object is structurally a `TData` with non-summed fields left\n * `undefined` — plug it into `pinnedBottomRowData={[totalRow]}`. Cell renderers\n * in the non-summed columns receive `undefined`, so they should render nothing\n * (all of the DS cell renderers short-circuit on `null`/`undefined`).\n *\n * Pass an optional `labelField` + `labelValue` to show a static caption such\n * as \"Total\" in the first column of the pinned row.\n */\nexport function useTotalRow<TData>(\n rowData: TData[] | undefined,\n sumFields: Array<keyof TData & string>,\n options?: {\n labelField?: keyof TData & string;\n labelValue?: string;\n },\n): TData {\n return useMemo(() => {\n const row: Record<string, unknown> = {};\n\n for (const field of sumFields) {\n let total = 0;\n for (const r of rowData ?? []) {\n const raw = (r as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n if (Number.isFinite(n)) total += n;\n }\n row[field] = total;\n }\n\n if (options?.labelField && options.labelValue !== undefined) {\n row[options.labelField] = options.labelValue;\n }\n\n return row as TData;\n }, [rowData, sumFields, options?.labelField, options?.labelValue]);\n}\n","import { useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { DateRangePicker } from '../../date-range-picker';\nimport type { DateRangeValue } from '../../date-range-picker';\n\n/**\n * Custom AG Grid filter component for date *ranges*. AG Grid Community's\n * built-in `agDateColumnFilter` only handles single-date comparison —\n * platform needs \"between X and Y\" for invoice / transaction lists.\n *\n * Wire on a colDef:\n * ```tsx\n * { field: 'date', filter: DateRangeFilter }\n * ```\n *\n * The filter model has shape `{ type: 'inRange', dateFrom, dateTo }` to\n * stay close to AG Grid's own date-filter convention so server-side\n * adapters can interpret it the same way.\n */\nexport interface DateRangeFilterModel {\n type: 'inRange';\n dateFrom: string | null;\n dateTo: string | null;\n}\n\nfunction toIsoDate(d: Date | undefined): string | null {\n if (!d) return null;\n return d.toISOString().slice(0, 10);\n}\n\nfunction fromIsoDate(s: string | null | undefined): Date | undefined {\n if (!s) return undefined;\n const d = new Date(s);\n return Number.isNaN(d.getTime()) ? undefined : d;\n}\n\nexport function DateRangeFilter(props: CustomFilterProps) {\n const { model, onModelChange, getValue, doesRowPassOtherFilter } = props;\n const initial: DateRangeValue = {\n from: fromIsoDate((model as DateRangeFilterModel | null)?.dateFrom),\n to: fromIsoDate((model as DateRangeFilterModel | null)?.dateTo),\n };\n const [range, setRange] = useState<DateRangeValue>(initial);\n\n // Tell AG Grid how to evaluate a row against the current model. AG Grid\n // calls this for each row; we read the cell value via `getValue(node)`\n // (a Date or ISO string), compare to the bounds.\n useGridFilter({\n doesFilterPass: (params) => {\n const cellValue = getValue(params.node) as\n | Date\n | string\n | null\n | undefined;\n if (!cellValue) return false;\n const cellDate =\n cellValue instanceof Date ? cellValue : fromIsoDate(String(cellValue));\n if (!cellDate) return false;\n if (range.from && cellDate < range.from) return false;\n if (range.to && cellDate > range.to) return false;\n // Respect other filters via the supplied callback if AG Grid uses\n // it (some grid setups call `doesRowPassOtherFilter` before us).\n void doesRowPassOtherFilter;\n return true;\n },\n });\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div className=\"ds:p-[var(--spacing-sm)] ds:min-w-[280px]\">\n <DateRangePicker value={range} onChange={apply} size=\"sm\" />\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `DateRangeFilter`.\n *\n * Renders the kit's `<DateRangePicker>` directly as the floating-filter\n * input — its built-in trigger button + calendar popover IS the filter\n * UI. Earlier versions wrapped the picker in a second `<Popover>`,\n * producing the \"click → empty popover with another trigger → click\n * again → calendar\" double-step that read as duplicated UI.\n */\nexport function DateRangeFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n DateRangeFilterModel\n >,\n) {\n const { model, onModelChange } = props;\n const [range, setRange] = useState<DateRangeValue>({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n });\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div data-component=\"date-range-floating-filter\" className=\"ds:w-full\">\n <DateRangePicker value={range} onChange={apply} size=\"sm\" />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Checkbox } from '../../checkbox';\nimport { Button } from '../../button';\nimport { MultiSelect } from '../../multi-select';\n\n/**\n * Custom AG Grid filter component — multi-select facet filter.\n *\n * The Community-friendly equivalent of AG Grid Enterprise's\n * `agSetColumnFilter`. Surfaces a checkbox list of every value the column\n * can take, so users tick to include / untick to exclude. Much faster than\n * the default `agTextColumnFilter` for closed enums (status, room,\n * operator).\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'status',\n * filter: SelectFilter,\n * filterParams: {\n * options: [\n * { value: 'open', label: 'Aperte' },\n * { value: 'paid', label: 'Pagate' },\n * ],\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'set', values: Array<string | number> }` matches\n * AG Grid Enterprise's set-filter convention so server-side adapters can\n * read either implementation the same way.\n */\n\nexport interface SelectFilterOption {\n value: string | number;\n label: string;\n}\n\nexport interface SelectFilterModel {\n type: 'set';\n values: Array<string | number>;\n}\n\nexport interface SelectFilterParams {\n options?: SelectFilterOption[];\n placeholder?: string;\n}\n\ntype SelectFilterValue = string | number;\n\nfunction toValueKey(v: SelectFilterValue): string {\n return typeof v === 'number' ? `n:${v}` : `s:${v}`;\n}\n\nexport function SelectFilter(\n props: CustomFilterProps<unknown, unknown, SelectFilterModel> &\n SelectFilterParams,\n) {\n const { model, onModelChange, getValue, api, column, options, placeholder } =\n props;\n const { t } = useTranslation('ui');\n\n // Universe of choices. Prefer the explicit `options` filterParam; fall\n // back to the column's distinct rendered values so the filter is useful\n // even when the consumer doesn't enumerate them. The fallback path runs\n // when `options` is omitted and the filter has access to the grid api\n // — `api.forEachNode` is a synchronous read so this is cheap per\n // mount. Consumers wanting a live-updating list should pass `options`.\n const derivedOptions = useMemo<SelectFilterOption[]>(() => {\n if (options && options.length > 0) return options;\n if (!api || !column) return [];\n const seen = new Map<string, SelectFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = getValue(node) as unknown;\n if (raw === null || raw === undefined) return;\n const value =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n if (!seen.has(key)) {\n seen.set(key, { value, label: String(value) });\n }\n });\n return Array.from(seen.values()).sort((a, b) =>\n String(a.label).localeCompare(String(b.label)),\n );\n }, [options, api, column, getValue]);\n\n // Working set — checkboxes mutate `pending` only; we commit to the\n // grid via `onModelChange` when the user clicks Apply (or clears).\n const initialSelected = useMemo<Set<string>>(() => {\n const set = new Set<string>();\n const incoming = model?.values ?? [];\n for (const v of incoming) set.add(toValueKey(v));\n return set;\n }, [model]);\n\n const [pending, setPending] = useState<Set<string>>(initialSelected);\n\n // Sync local `pending` if the model changes externally (e.g. when AG\n // Grid pushes a reset). `model` is the dependency — Set instances are\n // compared by reference in React, so the memo above is sufficient.\n useEffect(() => {\n setPending(initialSelected);\n }, [initialSelected]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const active = model?.values;\n if (!active || active.length === 0) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value: SelectFilterValue =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n return active.some((v) => toValueKey(v) === key);\n },\n });\n\n function toggle(optionKey: string) {\n setPending((prev) => {\n const next = new Set(prev);\n if (next.has(optionKey)) next.delete(optionKey);\n else next.add(optionKey);\n return next;\n });\n }\n\n function apply() {\n if (pending.size === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const opt of derivedOptions) {\n if (pending.has(toValueKey(opt.value))) values.push(opt.value);\n }\n onModelChange({ type: 'set', values });\n }\n\n function clear() {\n setPending(new Set());\n onModelChange(null);\n }\n\n const placeholderLabel = placeholder ?? t('dataTable.selectFilter.all');\n\n return (\n <div\n data-component=\"select-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[200px] ds:max-w-[260px]\"\n >\n <div\n role=\"group\"\n aria-label={placeholderLabel}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:max-h-[240px] ds:overflow-y-auto\"\n >\n {derivedOptions.length === 0 ? (\n <p className=\"ds:text-[length:var(--font-size-sm)] ds:text-[var(--muted-foreground)] ds:py-[var(--spacing-xs)]\">\n {t('dataTable.agGrid.noRowsToShow')}\n </p>\n ) : (\n derivedOptions.map((option) => {\n const key = toValueKey(option.value);\n return (\n <Checkbox\n key={key}\n size=\"sm\"\n label={option.label}\n checked={pending.has(key)}\n onCheckedChange={() => toggle(key)}\n />\n );\n })\n )}\n </div>\n <div className=\"ds:flex ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.selectFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.selectFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `SelectFilter`.\n *\n * Renders the kit's `<MultiSelect>` directly as the floating-filter\n * input — its built-in trigger + checkbox dropdown IS the filter UI.\n * Earlier versions wrapped MultiSelect in another `<Popover>`,\n * producing the \"click trigger → empty popover with another trigger →\n * click → checkbox list\" double-step that read as duplicated UI.\n *\n * MultiSelect's options use `string` values; we string-convert the\n * model's `(string | number)[]` for the trigger and parse back on\n * apply. The grid model still tracks the original primitive types so\n * `doesFilterPass` keeps matching numeric columns correctly.\n */\nexport function SelectFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n SelectFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as SelectFilterParams | undefined) ??\n {};\n const availableOptions = filterParams.options ?? [];\n\n // MultiSelect's `value` is `string[]`. SelectFilter's model carries\n // `(string | number)[]` so we string-convert in / out. Build a lookup\n // from the stringified key back to the original primitive so the\n // model retains the consumer's typing.\n const valueByKey = useMemo(() => {\n const map = new Map<string, SelectFilterValue>();\n for (const opt of availableOptions) map.set(String(opt.value), opt.value);\n return map;\n }, [availableOptions]);\n\n const selectOptions = useMemo(\n () =>\n availableOptions.map((opt) => ({\n value: String(opt.value),\n label: opt.label,\n })),\n [availableOptions],\n );\n\n const currentValue = useMemo(\n () => (model?.values ?? []).map((v) => String(v)),\n [model],\n );\n\n function handleChange(next: string[]) {\n if (next.length === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const k of next) {\n const original = valueByKey.get(k);\n if (original !== undefined) values.push(original);\n }\n onModelChange({ type: 'set', values });\n }\n\n return (\n <div data-component=\"select-floating-filter\" className=\"ds:w-full\">\n <MultiSelect\n size=\"sm\"\n options={selectOptions}\n value={currentValue}\n onChange={handleChange}\n placeholder={filterParams.placeholder}\n allowClear\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Autocomplete } from '../../autocomplete';\nimport { Button } from '../../button';\nimport type { OptionShape } from '../../_shared/option';\n\n/**\n * Custom AG Grid filter component — single-select typeahead filter.\n *\n * Wraps the kit's existing `<Autocomplete>` so the user types to filter a\n * bounded-but-large set of values (e.g. patient names), picks one\n * suggestion, and the grid filters to rows matching that value exactly.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'patient',\n * filter: TypeaheadFilter,\n * filterParams: {\n * options: PATIENTS.map(p => ({ value: p.name, label: p.name })),\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'equals', value: string }` matches AG Grid's\n * text-filter `equals` convention so server-side adapters can read either\n * implementation the same way.\n */\n\nexport interface TypeaheadFilterOption {\n value: string;\n label: string;\n}\n\nexport interface TypeaheadFilterModel {\n type: 'equals';\n value: string;\n}\n\nexport interface TypeaheadFilterParams {\n options?: TypeaheadFilterOption[];\n loadOptions?: (\n input: string,\n opts: { signal: AbortSignal; locale: string },\n ) => Promise<TypeaheadFilterOption[]>;\n placeholder?: string;\n}\n\nfunction normalise(s: string): string {\n return s.trim().toLocaleLowerCase();\n}\n\nexport function TypeaheadFilter(\n props: CustomFilterProps<unknown, unknown, TypeaheadFilterModel> &\n TypeaheadFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n api,\n column,\n options,\n loadOptions,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n // Universe of choices. Prefer explicit `options`; fall back to the\n // column's distinct values when neither `options` nor `loadOptions` is\n // supplied. Same shape as SelectFilter's derivation so the two filters\n // present a consistent experience when consumers don't enumerate.\n const derivedOptions = useMemo<TypeaheadFilterOption[]>(() => {\n if (options && options.length > 0) return options;\n if (!api || !column) return [];\n const seen = new Map<string, TypeaheadFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = getValue(node) as unknown;\n if (raw === null || raw === undefined) return;\n const value = typeof raw === 'string' ? raw : String(raw);\n if (!seen.has(value)) {\n seen.set(value, { value, label: value });\n }\n });\n return Array.from(seen.values()).sort((a, b) =>\n a.label.localeCompare(b.label),\n );\n }, [options, api, column, getValue]);\n\n // Build the async `loadOptions` adapter that <Autocomplete> consumes.\n // Local-options path filters the snapshot synchronously and wraps it\n // in Promise.resolve(); explicit `loadOptions` is passed through.\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? derivedOptions.filter((o) => normalise(o.label).includes(q))\n : derivedOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, derivedOptions]);\n\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const target = model?.value;\n if (!target) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value = typeof raw === 'string' ? raw : String(raw);\n return normalise(value) === normalise(target);\n },\n });\n\n function handleSelect(option: OptionShape) {\n // Autocomplete itself commits `option.label` to the input value; we\n // mirror that here so the displayed text matches what the user just\n // picked, even when label and value diverge (e.g. id vs name).\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n // Clear the applied model when the user empties the input so the\n // grid stops filtering as soon as the field is blank.\n if (next === '' && model) onModelChange(null);\n }\n\n function clear() {\n setDraft('');\n onModelChange(null);\n }\n\n const placeholderLabel =\n placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n return (\n <div\n data-component=\"typeahead-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n <div className=\"ds:flex ds:items-center ds:justify-end ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.typeaheadFilter.clear')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `TypeaheadFilter`.\n *\n * Renders the kit's `<Autocomplete>` directly as the floating-filter\n * input — its built-in text input + portaled dropdown IS the filter\n * UI. Earlier versions wrapped Autocomplete in a second `<Popover>`,\n * producing the \"click trigger → popover with another search input →\n * type → list appears\" double-step that read as duplicated UI.\n */\nexport function TypeaheadFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n TypeaheadFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as\n | TypeaheadFilterParams\n | undefined) ?? {};\n const availableOptions = filterParams.options ?? [];\n const loadOptions = filterParams.loadOptions;\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? availableOptions.filter((o) => normalise(o.label).includes(q))\n : availableOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, availableOptions]);\n\n // Track the input's display value separately from the applied model.\n // The user can type freely; we only apply when they pick an option\n // from the dropdown (committing a known value to the model). Clearing\n // the input clears the filter.\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n function handleSelect(option: OptionShape) {\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n if (next === '' && model) onModelChange(null);\n }\n\n return (\n <div data-component=\"typeahead-floating-filter\" className=\"ds:w-full\">\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { NumberInput } from '../../number-input';\nimport { Select } from '../../select';\nimport { Button } from '../../button';\n\n/**\n * Custom AG Grid filter component for numeric columns. AG Grid Community's\n * built-in `agNumberColumnFilter` paints a stock browser-skinned\n * `<input type=\"number\">` that does not match the kit's form language —\n * this wraps the DS `<NumberInput>` + `<Select>` so totals, prices,\n * quantities, etc. line up visually with neighbouring DS-styled cells.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'total',\n * filter: NumberFilter,\n * floatingFilterComponent: NumberFloatingFilter,\n * filterParams: { defaultOperator: 'greaterThan', min: 0 },\n * }\n * ```\n *\n * The full-popover variant exposes the operator dropdown (equals,\n * greaterThan, inRange, blank, …); the floating-filter row is a single\n * compact input whose operator is fixed to `defaultOperator`. Both speak\n * the same `NumberFilterModel` so server-side adapters can read either.\n *\n * Model shape `{ type, filter, filterTo? }` matches AG Grid's own\n * `agNumberColumnFilter` vocabulary so adapters can interchange.\n */\n\nexport type NumberFilterOperator =\n | 'equals'\n | 'notEqual'\n | 'greaterThan'\n | 'greaterThanOrEqual'\n | 'lessThan'\n | 'lessThanOrEqual'\n | 'inRange'\n | 'blank'\n | 'notBlank';\n\nexport interface NumberFilterModel {\n type: NumberFilterOperator;\n filter: number;\n filterTo?: number;\n}\n\nexport interface NumberFilterParams {\n defaultOperator?: NumberFilterOperator;\n min?: number;\n max?: number;\n step?: number;\n placeholder?: string;\n}\n\nconst ALL_OPERATORS: NumberFilterOperator[] = [\n 'equals',\n 'notEqual',\n 'greaterThan',\n 'greaterThanOrEqual',\n 'lessThan',\n 'lessThanOrEqual',\n 'inRange',\n 'blank',\n 'notBlank',\n];\n\nfunction operatorTakesValue(op: NumberFilterOperator): boolean {\n return op !== 'blank' && op !== 'notBlank';\n}\n\nfunction operatorTakesRange(op: NumberFilterOperator): boolean {\n return op === 'inRange';\n}\n\nfunction evaluate(\n op: NumberFilterOperator,\n cell: number | null,\n primary: number | null,\n secondary: number | null,\n): boolean {\n if (op === 'blank') return cell === null;\n if (op === 'notBlank') return cell !== null;\n if (cell === null) return false;\n if (primary === null) return true;\n switch (op) {\n case 'equals':\n return cell === primary;\n case 'notEqual':\n return cell !== primary;\n case 'greaterThan':\n return cell > primary;\n case 'greaterThanOrEqual':\n return cell >= primary;\n case 'lessThan':\n return cell < primary;\n case 'lessThanOrEqual':\n return cell <= primary;\n case 'inRange': {\n if (secondary === null) return cell >= primary;\n const lo = Math.min(primary, secondary);\n const hi = Math.max(primary, secondary);\n return cell >= lo && cell <= hi;\n }\n default:\n return true;\n }\n}\n\nfunction coerceCell(raw: unknown): number | null {\n if (raw === null || raw === undefined || raw === '') return null;\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isNaN(n) ? null : n;\n}\n\nexport function NumberFilter(\n props: CustomFilterProps<unknown, unknown, NumberFilterModel> &\n NumberFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n defaultOperator,\n min,\n max,\n step,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n const initialOperator: NumberFilterOperator =\n model?.type ?? defaultOperator ?? 'equals';\n const [operator, setOperator] =\n useState<NumberFilterOperator>(initialOperator);\n const [primary, setPrimary] = useState<number | null>(model?.filter ?? null);\n const [secondary, setSecondary] = useState<number | null>(\n model?.filterTo ?? null,\n );\n\n // If AG Grid pushes an externally-cleared / reset model, mirror it in\n // local state so the UI stays consistent with the applied filter.\n useEffect(() => {\n if (model === null) {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n return;\n }\n setOperator(model.type);\n setPrimary(model.filter ?? null);\n setSecondary(model.filterTo ?? null);\n }, [model, defaultOperator]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n if (!model) return true;\n const cell = coerceCell(getValue(params.node));\n return evaluate(\n model.type,\n cell,\n model.filter ?? null,\n model.filterTo ?? null,\n );\n },\n });\n\n const operatorOptions = useMemo(\n () =>\n ALL_OPERATORS.map((op) => ({\n value: op,\n label: t(`dataTable.numberFilter.operators.${op}`),\n })),\n [t],\n );\n\n const placeholderLabel =\n placeholder ?? t('dataTable.numberFilter.placeholder');\n\n function apply() {\n if (!operatorTakesValue(operator)) {\n onModelChange({ type: operator, filter: 0 });\n return;\n }\n if (primary === null) {\n onModelChange(null);\n return;\n }\n if (operatorTakesRange(operator)) {\n onModelChange({\n type: operator,\n filter: primary,\n filterTo: secondary ?? undefined,\n });\n return;\n }\n onModelChange({ type: operator, filter: primary });\n }\n\n function clear() {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n onModelChange(null);\n }\n\n const showValue = operatorTakesValue(operator);\n const showRange = operatorTakesRange(operator);\n\n return (\n <div\n data-component=\"number-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Select\n size=\"sm\"\n options={operatorOptions}\n value={operator}\n onValueChange={(next) => {\n if (next === '') return;\n setOperator(next as NumberFilterOperator);\n }}\n aria-label={t('dataTable.numberFilter.operators.equals')}\n />\n {showValue && !showRange && (\n <NumberInput\n size=\"sm\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n )}\n {showRange && (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <NumberInput\n size=\"sm\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.from')}\n aria-label={t('dataTable.numberFilter.from')}\n />\n <NumberInput\n size=\"sm\"\n value={secondary}\n onChange={setSecondary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.to')}\n aria-label={t('dataTable.numberFilter.to')}\n />\n </div>\n )}\n <div className=\"ds:flex ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.numberFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.numberFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `NumberFilter`.\n *\n * Renders the kit's `<NumberInput>` directly as the inline filter input\n * with a fixed operator (`defaultOperator`, or `'equals'`). The operator\n * dropdown lives only in the full popover — the floating-filter row is\n * deliberately compact, matching the way `agNumberColumnFilter` ships\n * with AG Grid Community.\n *\n * Debounced commit at 200 ms so each keystroke does not re-run the grid\n * filter. Empty input or invalid number commits `null` so the column\n * reverts to \"no filter\" rather than `filter: NaN`.\n */\nexport function NumberFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n NumberFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as NumberFilterParams | undefined) ??\n {};\n const operator: NumberFilterOperator =\n filterParams.defaultOperator ?? 'equals';\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.numberFilter.placeholder');\n\n const [draft, setDraft] = useState<number | null>(model?.filter ?? null);\n\n // Sync local draft when the model is reset externally (e.g. a global\n // clear from the column-header menu's \"Clear\" button).\n useEffect(() => {\n setDraft(model?.filter ?? null);\n }, [model?.filter]);\n\n // Debounced commit. We don't pull a hook in for this — a single\n // useEffect + setTimeout is cheaper than the cost of importing one,\n // and AG Grid only re-renders this floating filter per keystroke.\n useEffect(() => {\n if (draft === (model?.filter ?? null)) return;\n const handle = setTimeout(() => {\n if (draft === null || Number.isNaN(draft)) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: operator, filter: draft });\n }, 200);\n return () => clearTimeout(handle);\n // `model` intentionally excluded — we only want to react to user\n // edits of `draft`. Model resets sync via the effect above.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [draft, operator]);\n\n return (\n <div data-component=\"number-floating-filter\" className=\"ds:w-full\">\n <NumberInput\n size=\"sm\"\n value={draft}\n onChange={setDraft}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n </div>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Badge } from '../../badge/badge';\n\nexport type BadgeVariant = 'neutral' | 'info' | 'success' | 'warning' | 'error';\n\nexport interface StatusCellRendererParams {\n variantMap?: Record<string, BadgeVariant>;\n}\n\nexport function StatusCellRenderer(\n props: CustomCellRendererProps & StatusCellRendererParams,\n) {\n const { value, variantMap } = props;\n const variant: BadgeVariant = variantMap?.[value as string] ?? 'neutral';\n return (\n <Badge variant={variant} withDot size=\"sm\">\n {String(value ?? '')}\n </Badge>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface UserCellValue {\n name: string;\n src?: string;\n}\n\nexport function UserCellRenderer(\n props: CustomCellRendererProps<unknown, UserCellValue>,\n) {\n const { value } = props;\n if (!value) return null;\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Avatar name={value.name} src={value.src} size=\"sm\" />\n <span>{value.name}</span>\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface ImageCellRendererParams {\n /** Field name on the row whose value holds the image URL. */\n srcField: string;\n /** Optional field name holding alt text. Falls back to '' (decorative). */\n altField?: string;\n /**\n * Optional field name holding a name string. When the src URL is missing or\n * rejected, the cell falls back to `<Avatar name={fallback}>` so the cell\n * still has a visual.\n */\n fallbackField?: string;\n /** Visual size of the image. Matches `<Avatar>` sizes (sm=32, md=40, lg=48). */\n size?: 'sm' | 'md' | 'lg';\n /** Corner radius preset. `circle` matches `<Avatar>`. */\n shape?: 'square' | 'rounded' | 'circle';\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ImageCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-8',\n md: 'ds:size-10',\n lg: 'ds:size-12',\n};\n\nconst SHAPE_CLASS: Record<\n NonNullable<ImageCellRendererParams['shape']>,\n string\n> = {\n square: 'ds:rounded-none',\n rounded: 'ds:rounded-[var(--radius-md)]',\n circle: 'ds:rounded-[var(--radius-full)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Only accept http(s) and data: URLs. Reject `javascript:` / `vbscript:` /\n// any other smuggled scheme. Browsers won't execute non-image data: URLs in\n// `<img>`, but rejecting them in JS gives a single audit point.\nconst SAFE_SRC_RE = /^(?:https?:|data:image\\/)/i;\n\nfunction sanitizeSrc(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const trimmed = raw.trim();\n if (trimmed.length === 0) return undefined;\n return SAFE_SRC_RE.test(trimmed) ? trimmed : undefined;\n}\n\nexport function ImageCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ImageCellRendererParams,\n) {\n const {\n data,\n srcField,\n altField,\n fallbackField,\n size = 'md',\n shape = 'rounded',\n } = props;\n\n if (!data) return null;\n\n const rawSrc = readField(data, srcField);\n const src = sanitizeSrc(rawSrc);\n const alt = altField ? (readField(data, altField) ?? '') : '';\n const fallbackName = fallbackField\n ? readField(data, fallbackField)\n : undefined;\n\n if (!src) {\n if (fallbackName) {\n return <Avatar name={fallbackName} size={size} />;\n }\n return null;\n }\n\n return (\n <img\n src={src}\n alt={alt}\n loading=\"lazy\"\n decoding=\"async\"\n className={['ds:object-cover', SIZE_CLASS[size], SHAPE_CLASS[shape]].join(\n ' ',\n )}\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport { Tag } from '../../tag/tag';\nimport { Tooltip } from '../../tooltip';\n\nexport interface TagListCellRendererParams {\n maxVisible?: number;\n}\n\nexport function TagListCellRenderer(\n props: CustomCellRendererProps<unknown, string[]> & TagListCellRendererParams,\n) {\n const { value, maxVisible = 3 } = props;\n const { t } = useTranslation();\n\n if (!Array.isArray(value) || value.length === 0) return null;\n\n const visible = value.slice(0, maxVisible);\n const overflow = value.length - maxVisible;\n\n return (\n <span className=\"ds:inline-flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n {visible.map((tag) => (\n <Tag key={tag} label={tag} size=\"sm\" />\n ))}\n {overflow > 0 && (\n <Tooltip label={value.slice(maxVisible).join(', ')}>\n <Tag\n label={t('inputs.multiSelect.overflow', { count: overflow })}\n size=\"sm\"\n variant=\"neutral\"\n fill=\"outline\"\n />\n </Tooltip>\n )}\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Timestamp } from '../../timestamp';\n\nexport type DateCellFormat = 'date' | 'time' | 'datetime' | 'relative';\n\nexport interface DateCellRendererParams {\n /** Which preset to use. Default `'date'`. */\n format?: DateCellFormat;\n /** Escape hatch — overrides the preset entirely. */\n options?: Intl.DateTimeFormatOptions;\n}\n\nconst PRESETS: Record<\n Exclude<DateCellFormat, 'relative'>,\n Intl.DateTimeFormatOptions\n> = {\n date: { year: 'numeric', month: 'short', day: 'numeric' },\n time: { hour: '2-digit', minute: '2-digit' },\n datetime: {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n },\n};\n\nexport function DateCellRenderer(\n props: CustomCellRendererProps & DateCellRendererParams,\n) {\n const { value, format = 'date', options } = props;\n if (value == null || value === '') return null;\n\n // `shape=\"bare\"` keeps the cell font inherited from --ag-font-size. Timestamp\n // still emits a proper `<time dateTime>` for assistive tech and feeds.\n if (format === 'relative' && !options) {\n return <Timestamp value={value as string | Date} shape=\"bare\" />;\n }\n\n return (\n <Timestamp\n value={value as string | Date}\n format=\"absolute\"\n shape=\"bare\"\n absoluteFormat={\n options ?? PRESETS[format === 'relative' ? 'date' : format]\n }\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface CurrencyCellRendererParams {\n /** ISO 4217 currency code. Default `'EUR'`. */\n currency?: string;\n /** Apply a destructive color token to negative amounts. */\n colorNegative?: boolean;\n /** Render the value with strikethrough — used for written-off balances. */\n strikethrough?: boolean;\n /** `Intl.NumberFormat` escape hatch. Merged on top of currency defaults. */\n options?: Intl.NumberFormatOptions;\n}\n\nfunction toNumber(value: unknown): number | null {\n if (value == null || value === '') return null;\n const n = typeof value === 'number' ? value : Number(value);\n return Number.isFinite(n) ? n : null;\n}\n\nexport function CurrencyCellRenderer(\n props: CustomCellRendererProps & CurrencyCellRendererParams,\n) {\n const {\n value,\n currency = 'EUR',\n colorNegative,\n strikethrough,\n options,\n } = props;\n const { i18n } = useTranslation();\n const n = toNumber(value);\n if (n === null) return null;\n\n const locale = i18n.language || 'en';\n const formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n ...options,\n }).format(n);\n\n const classNames = ['ds:tabular-nums'];\n if (colorNegative && n < 0)\n classNames.push('ds:text-[color:var(--destructive)]');\n if (strikethrough) classNames.push('line-through');\n\n return <span className={classNames.join(' ')}>{formatted}</span>;\n}\n","import { cloneElement, isValidElement, type ReactNode } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { IconButton } from '../../button/icon-button';\n\n// Lucide icons render at their intrinsic 24×24 unless given a `size` prop or\n// `size-*` class. The IconButton's wrapping span is only `size-4` (16px), so a\n// bare `<Trash2 />` overflows and, inside AG Grid's `overflow: hidden` cells,\n// gets clipped into horizontal slivers. Coerce icon nodes to the expected size.\nfunction sizeIcon(node: ReactNode): ReactNode {\n if (!isValidElement(node)) return node;\n const element = node as React.ReactElement<{\n className?: string;\n size?: number;\n }>;\n const existingClass = element.props.className ?? '';\n const className = /\\bsize-|\\bw-|\\bh-/.test(existingClass)\n ? existingClass\n : `${existingClass} size-4`.trim();\n return cloneElement(element, { className, size: element.props.size ?? 16 });\n}\n\nexport interface ActionDef<TData = unknown> {\n /** Lucide-style icon node. */\n icon: ReactNode;\n /** Accessible label — also used as the tooltip. */\n label: string;\n /** Invoked with the row data. */\n onClick: (data: TData) => void;\n /** Disable the action. Pass a predicate for per-row disablement. */\n disabled?: boolean | ((data: TData) => boolean);\n /** Human-readable reason shown in the tooltip when disabled. */\n disabledReason?: string;\n /** `destructive` swaps the button intent. */\n variant?: 'default' | 'destructive';\n /** Hide the action entirely. Pass a predicate for per-row hiding. */\n hidden?: boolean | ((data: TData) => boolean);\n}\n\nexport interface ActionsCellRendererParams<TData = unknown> {\n actions: ActionDef<TData>[];\n}\n\nfunction resolve<T>(\n flag: boolean | ((data: T) => boolean) | undefined,\n data: T,\n): boolean {\n if (typeof flag === 'function') return flag(data);\n return Boolean(flag);\n}\n\nexport function ActionsCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ActionsCellRendererParams<TData>,\n) {\n const { data, actions } = props;\n if (!data) return null;\n\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {actions.map((action, index) => {\n if (resolve(action.hidden, data)) return null;\n const isDisabled = resolve(action.disabled, data);\n const tooltip =\n isDisabled && action.disabledReason\n ? action.disabledReason\n : action.label;\n\n const isDestructive = action.variant === 'destructive';\n\n return (\n <IconButton\n // Action defs are referentially stable from consumers; index is\n // acceptable here because actions do not reorder within a row.\n\n key={index}\n size=\"sm\"\n intent=\"ghost\"\n icon={sizeIcon(action.icon)}\n tooltip={tooltip}\n aria-label={action.label}\n disabled={isDisabled}\n onClick={(event) => {\n event.stopPropagation();\n action.onClick(data);\n }}\n className={\n isDestructive\n ? 'ds:text-[color:var(--destructive)] ds:hover:text-[color:var(--destructive-hover)]'\n : undefined\n }\n />\n );\n })}\n </span>\n );\n}\n","import type { MouseEvent } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\n\ntype Getter<T, TData> = T | ((data: TData) => T | undefined);\n\nexport interface LinkCellRendererParams<TData = unknown> {\n /** Anchor href — or a function that derives it from the row. */\n href?: Getter<string, TData>;\n /** Fallback / additional onClick. Prevents default when provided without href. */\n onClick?: (data: TData) => void;\n /** Small text rendered below the link — supports a row-aware function. */\n secondary?: Getter<string, TData>;\n}\n\nfunction resolve<T, TData>(\n source: Getter<T, TData> | undefined,\n data: TData,\n): T | undefined {\n if (typeof source === 'function') {\n return (source as (data: TData) => T | undefined)(data);\n }\n return source;\n}\n\nfunction safeHref(href: string): string {\n return /^(https?:\\/\\/|\\/|#|mailto:|tel:)/i.test(href) ? href : '#';\n}\n\nexport function LinkCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & LinkCellRendererParams<TData>,\n) {\n const { value, data, href, onClick, secondary } = props;\n if (!data) return null;\n\n const resolvedHref = resolve(href, data);\n const resolvedSecondary = resolve(secondary, data);\n const content = value == null || value === '' ? '' : String(value);\n\n const linkClasses = [\n 'ds:text-[color:var(--primary)]',\n 'ds:hover:underline',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:rounded-[var(--radius-sm)]',\n ].join(' ');\n\n const handleClick = (event: MouseEvent) => {\n if (!onClick) return;\n if (!resolvedHref) event.preventDefault();\n event.stopPropagation();\n onClick(data);\n };\n\n return (\n <span className=\"ds:flex ds:flex-col ds:leading-tight\">\n {resolvedHref ? (\n <a\n href={safeHref(resolvedHref)}\n onClick={handleClick}\n className={linkClasses}\n >\n {content}\n </a>\n ) : (\n <button\n type=\"button\"\n onClick={handleClick}\n className={[\n 'ds:appearance-none ds:bg-transparent ds:p-0 ds:text-start',\n linkClasses,\n ].join(' ')}\n >\n {content}\n </button>\n )}\n {resolvedSecondary ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {resolvedSecondary}\n </span>\n ) : null}\n </span>\n );\n}\n","import { useState, type ReactNode } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { CheckSquare, Square } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface ToggleCellRendererParams<TData = unknown> {\n /**\n * Fires with the row and the new target value. May return a `Promise` —\n * if it rejects, the consumer is expected to revert the underlying value\n * and flash the row with `data-table-row-error` (return that row class\n * from `getRowClass`). Use `onError` below to be notified inside this\n * renderer.\n */\n onToggle: (data: TData, newValue: boolean) => void | Promise<void>;\n /**\n * Optional reject hook. Fires when the `onToggle` promise rejects, with\n * the row and the error. The button auto-disables during the in-flight\n * promise and re-enables on either settle.\n */\n onError?: (data: TData, error: unknown) => void;\n /** Icon shown when the current value is truthy. */\n trueIcon?: ReactNode;\n /** Icon shown when the current value is falsy. */\n falseIcon?: ReactNode;\n /** Extra classes applied to the \"on\" icon — defaults to success token. */\n trueClass?: string;\n /** Extra classes applied to the \"off\" icon. */\n falseClass?: string;\n /** Accessible label. Falls back to the default on/off announcements. */\n label?: string;\n}\n\nexport function ToggleCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData, boolean> &\n ToggleCellRendererParams<TData>,\n) {\n const {\n value,\n data,\n onToggle,\n onError,\n trueIcon,\n falseIcon,\n trueClass = 'ds:text-[color:var(--success)]',\n falseClass = 'ds:text-[color:var(--muted-foreground)]',\n label,\n } = props;\n const { t } = useTranslation();\n const [pending, setPending] = useState(false);\n if (!data) return null;\n\n const isOn = Boolean(value);\n const icon = isOn\n ? (trueIcon ?? <CheckSquare aria-hidden className=\"ds:size-4\" />)\n : (falseIcon ?? <Square aria-hidden className=\"ds:size-4\" />);\n const stateClass = isOn ? trueClass : falseClass;\n const resolvedLabel =\n label ?? (isOn ? t('inputs.switch.on') : t('inputs.switch.off'));\n\n async function handleClick(event: React.MouseEvent) {\n event.stopPropagation();\n if (pending || !data) return;\n const next = !isOn;\n const result = onToggle(data, next);\n if (result && typeof (result as Promise<void>).then === 'function') {\n setPending(true);\n try {\n await result;\n } catch (err) {\n onError?.(data, err);\n } finally {\n setPending(false);\n }\n }\n }\n\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={isOn}\n aria-busy={pending}\n aria-label={resolvedLabel}\n disabled={pending}\n onClick={handleClick}\n className={[\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:appearance-none ds:bg-transparent ds:p-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:disabled:opacity-50',\n stateClass,\n ].join(' ')}\n >\n {icon}\n </button>\n );\n}\n","import { useRef } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useIsomorphicLayoutEffect } from '../../../hooks/use-isomorphic-layout-effect';\n\nexport interface ColorDotCellRendererParams {\n /** Field name on the row whose value holds the hex color. */\n colorField: string;\n /** Visual size of the dot. */\n size?: 'sm' | 'md' | 'lg';\n /** Optional label shown next to the dot. */\n labelField?: string;\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ColorDotCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-[var(--icon-size-sm)]',\n md: 'ds:size-[var(--icon-size-md)]',\n lg: 'ds:size-[var(--icon-size-lg)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Only accept trusted CSS color forms. Anything outside this allow-list\n// (including smuggled `url()` or extra declarations) is dropped so the\n// CSS custom-property writer can't be used to inject styles.\nconst HEX_RE = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGB_RE = /^rgba?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst HSL_RE = /^hsla?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst CSS_VAR_RE = /^var\\(--[a-z0-9-]+(?:,\\s*[^)]+)?\\)$/i;\n\nfunction sanitizeColor(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const v = raw.trim();\n if (\n HEX_RE.test(v) ||\n RGB_RE.test(v) ||\n HSL_RE.test(v) ||\n CSS_VAR_RE.test(v)\n ) {\n return v;\n }\n return undefined;\n}\n\nexport function ColorDotCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ColorDotCellRendererParams,\n) {\n const { data, colorField, size = 'md', labelField } = props;\n const dotRef = useRef<HTMLSpanElement | null>(null);\n const rawColor = data ? readField(data, colorField) : undefined;\n const color = sanitizeColor(rawColor);\n const label = data && labelField ? readField(data, labelField) : undefined;\n\n // Apply the dynamic color via a CSS custom property on the element.\n // Keeps hex/rgb literals out of JSX (constraint #2 and #4). The data\n // itself drives the color — constraints only forbid hardcoded colors\n // in component source, not in consumer row data.\n useIsomorphicLayoutEffect(() => {\n const el = dotRef.current;\n if (!el) return;\n if (color) {\n el.style.setProperty('--data-table-dot-color', color);\n } else {\n el.style.removeProperty('--data-table-dot-color');\n }\n }, [color]);\n\n if (!color) return null;\n\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span\n ref={dotRef}\n aria-hidden=\"true\"\n className={[\n 'ds:inline-block ds:shrink-0 ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--data-table-dot-color)]',\n 'ds:border ds:border-[color:var(--border)]',\n SIZE_CLASS[size],\n ].join(' ')}\n />\n {label ? <span>{label}</span> : null}\n </span>\n );\n}\n","import type { ColDef } from 'ag-grid-community';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface BalanceLine {\n /** User-visible label for this line. */\n label: string;\n /** Field name on the row whose numeric value is rendered. */\n valueField: string;\n /** `'currency'` renders via Intl, `'percent'` appends `%`, `'number'` raw. Default `'number'`. */\n format?: 'currency' | 'percent' | 'number';\n}\n\nexport interface BalanceCellRendererParams {\n lines: BalanceLine[];\n /** ISO 4217 code, used by `currency`-formatted lines. Default `'EUR'`. */\n currency?: string;\n /** Apply destructive color to negative values. */\n highlightNegative?: boolean;\n}\n\nfunction readNumber(row: unknown, field: string): number | null {\n if (!row || typeof row !== 'object') return null;\n const raw = (row as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isFinite(n) ? n : null;\n}\n\n/**\n * Renders a compact set of label / value pairs inside a single AG Grid cell.\n *\n * Layout is **horizontal** with middle-dot separators so the cell fits\n * inside the default AG Grid row height without spilling into the row\n * below. Use the SALDI / Listini patterns (Totale · Incassato · Da Incassare)\n * as the canonical example.\n *\n * If a consumer's content wraps (long localized labels, narrow columns)\n * they can opt into row auto-growth by spreading\n * {@link balanceCellRendererColDefDefaults} onto the column definition.\n */\nexport function BalanceCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & BalanceCellRendererParams,\n) {\n const { data, lines, currency = 'EUR', highlightNegative } = props;\n const { i18n } = useTranslation();\n if (!data) return null;\n\n const locale = i18n.language || 'en';\n\n const formatLine = (\n line: BalanceLine,\n ): { label: string; formatted: string; negative: boolean } | null => {\n const n = readNumber(data, line.valueField);\n if (n === null) return null;\n\n let formatted: string;\n switch (line.format ?? 'number') {\n case 'currency':\n formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n }).format(n);\n break;\n case 'percent':\n formatted = new Intl.NumberFormat(locale, {\n style: 'percent',\n maximumFractionDigits: 1,\n }).format(n / 100);\n break;\n default:\n formatted = new Intl.NumberFormat(locale).format(n);\n }\n\n return {\n label: line.label,\n formatted,\n negative: Boolean(highlightNegative) && n < 0,\n };\n };\n\n const rendered = lines\n .map(formatLine)\n .filter(\n (x): x is { label: string; formatted: string; negative: boolean } =>\n x !== null,\n );\n if (rendered.length === 0) return null;\n\n return (\n <div\n className={[\n 'ds:flex',\n 'ds:flex-wrap',\n 'ds:items-center',\n 'ds:gap-x-[var(--spacing-sm)]',\n 'ds:gap-y-0',\n 'type-meta',\n 'ds:leading-tight',\n ].join(' ')}\n >\n {rendered.map((item, idx) => (\n <span\n key={`${item.label}-${idx}`}\n className=\"ds:inline-flex ds:items-baseline ds:gap-x-[var(--spacing-xs)]\"\n >\n {idx > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:me-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\"\n >\n ·\n </span>\n ) : null}\n <span className=\"ds:text-[color:var(--muted-foreground)]\">\n {item.label}\n </span>\n <span\n className={[\n 'ds:tabular-nums',\n 'ds:font-medium',\n item.negative ? 'ds:text-[color:var(--destructive)]' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {item.formatted}\n </span>\n </span>\n ))}\n </div>\n );\n}\n\n/**\n * Column-definition defaults consumers can spread onto a `ColDef` when they\n * want the renderer's wrapped / multi-line behaviour to grow the row.\n *\n * The default compact horizontal layout is engineered to fit the standard\n * AG Grid row height, so this opt-in is only needed when a long label set\n * wraps across two or more lines and the consumer would rather grow the\n * row than wrap silently.\n *\n * AG Grid does NOT auto-grow row height to fit a tall cell unless\n * `autoHeight` and `wrapText` are set on the colDef itself — a cell\n * renderer can't impose that from inside.\n *\n * @example\n * ```ts\n * {\n * headerName: 'Saldi',\n * cellRenderer: BalanceCellRenderer,\n * cellRendererParams: { lines, currency: 'EUR' },\n * ...balanceCellRendererColDefDefaults,\n * }\n * ```\n */\nexport const balanceCellRendererColDefDefaults: Readonly<\n Pick<ColDef, 'autoHeight' | 'wrapText'>\n> = {\n autoHeight: true,\n wrapText: true,\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\n/**\n * Inline text editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The cell renderer (default\n * or custom) takes over again once editing stops.\n *\n * AG Grid commits on Enter or Tab or blur; cancels on Escape. The consumer\n * receives the committed value via `onCellValueChanged`.\n */\nexport function EditableTextCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, string>,\n) {\n const { initialValue, onValueChange, stopEditing, column } = props;\n const [value, setValue] = useState<string>(initialValue ?? '');\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Focus + select on mount so typing replaces the current value.\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n // The current value is pushed to AG Grid via `onValueChange` on every\n // keystroke — AG Grid commits the most recent value when editing stops.\n // No `useGridCellEditor` hook needed for that contract.\n\n // Thread the column header into the input's accessible name so screen\n // readers announce \"Edit text, {column}\" instead of an unlabelled input.\n // AG Grid doesn't auto-wire the column header to cell editors.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setValue(next);\n onValueChange(next);\n }}\n onKeyDown={(e) => {\n // Escape cancels, Enter/Tab commit — AG Grid handles both, but we\n // explicitly stop editing on Enter so the consumer sees the commit\n // immediately rather than waiting for the next focus blur.\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none',\n // Input surface chrome: rounded border + bg + focus halo.\n INPUT_SURFACE_CHROME,\n // Use the `md` height (`--min-target-size`) so the input\n // auto-lifts to 48px under `.theme-accessible` to satisfy\n // WCAG 2.5.5 target size.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\nexport interface EditableCurrencyCellEditorParams {\n /** ISO 4217 currency code (e.g. `EUR`, `USD`). Defaults to `EUR`. */\n currency?: string;\n /** Decimal places allowed in the editor. Defaults to 2 (cents precision). */\n decimals?: number;\n /** Minimum allowed value — values below this are clamped on commit. */\n min?: number;\n /** Maximum allowed value — values above this are clamped on commit. */\n max?: number;\n}\n\n/**\n * Inline numeric editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The display formatting is\n * still the renderer's job — once editing stops, the cell hands back to\n * `CurrencyCellRenderer` (or whichever renderer the colDef declares).\n *\n * Stores a Number, not a string, so consumers receive `row.amount = 12.5`\n * not `\"12.5\"`. Strips locale separators on each change so commas/dots in\n * any language convert to a clean numeric value.\n */\nexport function EditableCurrencyCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, number> &\n EditableCurrencyCellEditorParams,\n) {\n const {\n initialValue,\n onValueChange,\n stopEditing,\n column,\n decimals = 2,\n min,\n max,\n } = props;\n const { i18n } = useTranslation();\n const inputRef = useRef<HTMLInputElement | null>(null);\n // Thread the column header into the input's accessible name — see\n // editable-text-cell-renderer.tsx for the rationale.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n // Local string state so the user can type intermediate values like \"12.\"\n // before the trailing zero arrives. We commit a Number to AG Grid on each\n // change for consumers that watch row state live; the final commit fires\n // when editing stops.\n const [draft, setDraft] = useState<string>(() => {\n if (initialValue == null || Number.isNaN(initialValue)) return '';\n return String(initialValue);\n });\n\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n function parseDraft(input: string): number | null {\n if (input.trim().length === 0) return null;\n // Accept either the user's locale decimal separator or a `.`. Strip\n // grouping characters (locale thousands separators, plus spaces).\n const lang = i18n.language || 'en';\n const partsFmt = new Intl.NumberFormat(lang).formatToParts(12345.6);\n const groupChar = partsFmt.find((p) => p.type === 'group')?.value ?? '';\n const decimalChar =\n partsFmt.find((p) => p.type === 'decimal')?.value ?? '.';\n const cleaned = input\n .replace(new RegExp(`\\\\${groupChar}`, 'g'), '')\n .replace(decimalChar, '.')\n .replace(/[^\\d.-]/g, '');\n const n = Number(cleaned);\n return Number.isFinite(n) ? n : null;\n }\n\n function commit(input: string) {\n const parsed = parseDraft(input);\n if (parsed == null) {\n onValueChange(null);\n return;\n }\n // Clamp first, then round to the declared precision so we never\n // persist floating-point dust from string parsing.\n let clamped = parsed;\n if (typeof min === 'number') clamped = Math.max(min, clamped);\n if (typeof max === 'number') clamped = Math.min(max, clamped);\n const factor = 10 ** decimals;\n onValueChange(Math.round(clamped * factor) / factor);\n }\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n // Inputmode hints mobile keyboards to show the decimal pad instead\n // of the full keyboard. type=\"number\" would also work but spinners\n // and locale parsing are inconsistent across browsers.\n inputMode=\"decimal\"\n value={draft}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setDraft(next);\n commit(next);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n // Escape — AG Grid cancels by default; the editor doesn't need\n // explicit handling beyond what AG Grid wires automatically.\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none ds:text-end ds:tabular-nums',\n INPUT_SURFACE_CHROME,\n // Use `md` height — see editable-text-cell-renderer for rationale.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n"],"names":["__iconNode","Columns2","createLucideIcon","sizeIcon","node","isValidElement","element","existingClass","className","cloneElement","ToolbarContext","createContext","useToolbarContext","caller","ctx","useContext","ToolbarProvider","getApi","selectionCount","onPrint","children","value","useMemo","jsx","TOOLBAR_BASE","ToolbarRoot","forwardRef","props","ref","FilterBar","Actions","ExportCsv","label","onExport","intent","rest","t","useTranslation","handleClick","useCallback","api","IconButton","Download","resolveTokenToRgb","varName","fallback","probe","computed","match","defaultExportPdf","options","jsPDF","autoTable","n","visibleColumns","col","head","body","cells","headerFill","headerText","bodyText","alternateFill","doc","ExportPdf","onClick","fileName","FileText","Print","Printer","QuickSearch","placeholder","debounceMs","setValue","useState","timerRef","useRef","useEffect","TextInput","e","Search","Refresh","onRefresh","RefreshCw","describeFilterModel","model","m","type","filterTo","FilterChips","chips","setChips","quickFilter","setQuickFilter","refresh","cols","next","colId","c","headerName","qf","handler","_event","clearOne","clearAll","jsxs","Tag","Button","X","FacetFilter","field","active","setActive","apply","opt","isActive","DEFAULT_EXPORT_ITEMS","defaultExportXlsx","ExcelJS","workbook","sheet","headerRow","hex","r","g","b","cell","buffer","blob","url","link","ExportMenuContext","useExportMenuContext","ExportMenu","itemsContent","f","ExportMenuItem","DropdownMenu","defaultLabel","format","defaultIcon","FileSpreadsheet","readColumnEntries","ColumnToggle","open","setOpen","columns","setColumns","draggingColId","setDraggingColId","dragOverColId","setDragOverColId","toggleColumn","nextVisible","prev","moveColumn","fromColId","toColId","fromIdx","toIdx","moved","labelText","Popover","Columns","isDragging","isDragOver","GripVertical","Checkbox","checked","BulkAction","icon","variant","size","ExportMenuNamespace","Toolbar","OPERATORS","makeMatcher","locale","collator","indexOf","haystack","needle","i","a","coerceToString","raw","TextFilter","onModelChange","getValue","defaultOperator","initialOperator","operator","setOperator","draft","setDraft","matcher","i18next","useGridFilter","params","clear","operatorOptions","op","placeholderLabel","Select","event","TextFloatingFilter","column","filterParams","_b","_a","timer","clearImmediate","dataTableAgent","handle","args","ModuleRegistry","AllCommunityModule","dataTableVariants","cva","useAgLocaleText","DefaultLoadingOverlay","_","Skeleton","DefaultNoRowsOverlay","EmptyState","loadColumnState","gridId","saveColumnState","DataTableInner","columnDefs","rowData","rowSelection","pagination","paginationPageSize","paginationPageSizeSelector","onSelectionChanged","onSortChanged","onFilterChanged","noRowsOverlay","loadingOverlay","gridOptions","density","bordered","heightClass","getRowClass","pinnedBottomRowData","printMode","i18n","agGridRef","setSelectionCount","sortAnnouncement","setSortAnnouncement","localeText","ids","want","fromId","toId","ordered","lo","hi","target","page","useImperativeHandle","useAgentRegistration","isRtl","isLoading","prefersReducedMotion","usePrefersReducedMotion","resolvedTheme","useTheme","effectiveDensity","rowSelectionOption","handleGridReady","saved","handleColumnStateChange","handleSelectionChanged","rows","handleSortChanged","sortedCol","colDef","colName","dirKey","handleFilterChanged","id","NoRowsComponent","LoadingComponent","handlePrint","wrapperClass","toolbarContent","paginationEnabled","AgGridReact","DataTableBase","DataTable","useTotalRow","sumFields","row","total","toIsoDate","d","fromIsoDate","s","DateRangeFilter","doesRowPassOtherFilter","initial","range","setRange","cellValue","cellDate","DateRangePicker","DateRangeFloatingFilter","toValueKey","v","SelectFilter","derivedOptions","seen","key","initialSelected","set","incoming","pending","setPending","toggle","optionKey","values","option","SelectFloatingFilter","availableOptions","valueByKey","map","selectOptions","currentValue","handleChange","k","original","MultiSelect","normalise","TypeaheadFilter","loadOptions","adapterLoadOptions","query","opts","o","q","handleSelect","Autocomplete","TypeaheadFloatingFilter","ALL_OPERATORS","operatorTakesValue","operatorTakesRange","evaluate","primary","secondary","coerceCell","NumberFilter","min","max","step","setPrimary","setSecondary","showValue","showRange","NumberInput","NumberFloatingFilter","StatusCellRenderer","variantMap","Badge","UserCellRenderer","Avatar","SIZE_CLASS","SHAPE_CLASS","readField","SAFE_SRC_RE","sanitizeSrc","trimmed","ImageCellRenderer","data","srcField","altField","fallbackField","shape","rawSrc","src","alt","fallbackName","TagListCellRenderer","maxVisible","visible","overflow","tag","Tooltip","PRESETS","DateCellRenderer","Timestamp","toNumber","CurrencyCellRenderer","currency","colorNegative","strikethrough","formatted","classNames","resolve","flag","ActionsCellRenderer","actions","action","index","isDisabled","tooltip","isDestructive","source","safeHref","href","LinkCellRenderer","resolvedHref","resolvedSecondary","content","linkClasses","ToggleCellRenderer","onToggle","onError","trueIcon","falseIcon","trueClass","falseClass","isOn","CheckSquare","Square","stateClass","resolvedLabel","result","err","HEX_RE","RGB_RE","HSL_RE","CSS_VAR_RE","sanitizeColor","ColorDotCellRenderer","colorField","labelField","dotRef","rawColor","color","useIsomorphicLayoutEffect","el","readNumber","BalanceCellRenderer","lines","highlightNegative","formatLine","line","rendered","x","item","idx","EditableTextCellRenderer","initialValue","onValueChange","stopEditing","inputRef","INPUT_SURFACE_CHROME","INPUT_SURFACE_HEIGHT","INPUT_SURFACE_TEXT","INPUT_SURFACE_PADDING_X","EditableCurrencyCellRenderer","decimals","parseDraft","input","lang","partsFmt","groupChar","p","decimalChar","cleaned","commit","parsed","clamped","factor"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"editable-currency-cell-renderer-BQgaKFCz.js","sources":["../../node_modules/lucide-react/dist/esm/icons/columns-2.js","../../src/components/data-table/toolbar.tsx","../../src/components/data-table/filters/text-filter.tsx","../../src/components/data-table/data-table.agent.ts","../../src/components/data-table/data-table.tsx","../../src/components/data-table/hooks/use-total-row.ts","../../src/components/data-table/filters/date-range-filter.tsx","../../src/components/data-table/filters/select-filter.tsx","../../src/components/data-table/filters/typeahead-filter.tsx","../../src/components/data-table/filters/number-filter.tsx","../../src/components/data-table/cell-renderers/status-cell-renderer.tsx","../../src/components/data-table/cell-renderers/user-cell-renderer.tsx","../../src/components/data-table/cell-renderers/image-cell-renderer.tsx","../../src/components/data-table/cell-renderers/tag-list-cell-renderer.tsx","../../src/components/data-table/cell-renderers/date-cell-renderer.tsx","../../src/components/data-table/cell-renderers/currency-cell-renderer.tsx","../../src/components/data-table/cell-renderers/actions-cell-renderer.tsx","../../src/components/data-table/cell-renderers/link-cell-renderer.tsx","../../src/components/data-table/cell-renderers/toggle-cell-renderer.tsx","../../src/components/data-table/cell-renderers/color-dot-cell-renderer.tsx","../../src/components/data-table/cell-renderers/balance-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-text-cell-renderer.tsx","../../src/components/data-table/cell-renderers/editable-currency-cell-renderer.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }]\n];\nconst Columns2 = createLucideIcon(\"columns-2\", __iconNode);\n\nexport { __iconNode, Columns2 as default };\n//# sourceMappingURL=columns-2.js.map\n","import {\n cloneElement,\n createContext,\n forwardRef,\n isValidElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n Columns,\n Download,\n FileSpreadsheet,\n FileText,\n GripVertical,\n Printer,\n RefreshCw,\n Search,\n X,\n} from 'lucide-react';\nimport type { FilterChangedEvent, GridApi } from 'ag-grid-community';\nimport { Button, type ButtonProps } from '../button/button';\nimport { IconButton, type IconButtonProps } from '../button/icon-button';\nimport { Popover } from '../popover/popover';\nimport { Checkbox } from '../checkbox/checkbox';\nimport { TextInput } from '../text-input';\nimport { Tag } from '../tag';\nimport { DropdownMenu } from '../dropdown-menu';\n\n// Lucide icons default to 24×24 regardless of the wrapping span size, so\n// Button's `startIcon` slot (size-4 span) can't shrink them. Coerce icon\n// nodes to the `sm` button's 16px rendered size before handing them off.\nfunction sizeIcon(node: ReactNode): ReactNode {\n if (!isValidElement(node)) return node;\n const element = node as React.ReactElement<{\n className?: string;\n size?: number;\n }>;\n const existingClass = element.props.className ?? '';\n const className = /\\bsize-|\\bw-|\\bh-/.test(existingClass)\n ? existingClass\n : `${existingClass} ds:size-4`.trim();\n return cloneElement(element, { className, size: element.props.size ?? 16 });\n}\n\n/* ------------------------------------------------------------------ */\n/* Context */\n/* ------------------------------------------------------------------ */\n\ninterface ToolbarContextValue {\n /** Accessor to the live AG Grid API. Returns `undefined` until mount. */\n getApi: () => GridApi | undefined;\n /** Number of rows currently selected (re-renders on selection change). */\n selectionCount: number;\n /** Trigger the browser print dialog for the grid. */\n onPrint: () => void;\n}\n\nconst ToolbarContext = createContext<ToolbarContextValue | null>(null);\n\nfunction useToolbarContext(caller: string): ToolbarContextValue {\n const ctx = useContext(ToolbarContext);\n if (!ctx) {\n throw new Error(\n `${caller} must be rendered inside <DataTable.Toolbar> as a descendant of <DataTable>.`,\n );\n }\n return ctx;\n}\n\nexport interface ToolbarProviderProps {\n getApi: () => GridApi | undefined;\n selectionCount: number;\n onPrint: () => void;\n children: ReactNode;\n}\n\nexport function ToolbarProvider({\n getApi,\n selectionCount,\n onPrint,\n children,\n}: ToolbarProviderProps) {\n const value = useMemo(\n () => ({ getApi, selectionCount, onPrint }),\n [getApi, selectionCount, onPrint],\n );\n return (\n <ToolbarContext.Provider value={value}>{children}</ToolbarContext.Provider>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Toolbar root */\n/* ------------------------------------------------------------------ */\n\nconst TOOLBAR_BASE = [\n 'data-table-toolbar',\n // Mobile (<sm) keeps `flex-wrap` so a wide QuickSearch can flow above the\n // Actions cluster on narrow screens. From `sm` (≥640px) we switch to\n // `flex-nowrap` + `min-w-0` so the row stays single-line at every common\n // desktop width (1024 / 1280 / 1440) — the QuickSearch slot shrinks via\n // its own `min-w-0` instead of pushing the trailing Actions to a new row.\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:sm:flex-nowrap ds:min-w-0',\n // Brand-polish: give the toolbar its own card surface so it doesn't\n // sit flush above the grid as a bare row. The `--card` token resolves to\n // `--background` on the default light theme (white), which makes a\n // shadow-only chrome invisible on the page — pair the card fill with the\n // standard `--card-border` outline (same recipe as `<Card>`) so the\n // toolbar reads as a discrete surface in both light and dark themes.\n 'ds:bg-[var(--card)] ds:rounded-[var(--radius-md)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:shadow-[var(--shadow-sm)]',\n 'ds:py-[var(--spacing-sm)] ds:px-[var(--spacing-md)]',\n].join(' ');\n\nexport type ToolbarRootProps = HTMLAttributes<HTMLDivElement>;\n\nconst ToolbarRoot = forwardRef<HTMLDivElement, ToolbarRootProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n role=\"toolbar\"\n className={[TOOLBAR_BASE, className ?? ''].join(' ').trim()}\n {...props}\n >\n {children}\n </div>\n ),\n);\nToolbarRoot.displayName = 'DataTable.Toolbar';\n\n/* ------------------------------------------------------------------ */\n/* FilterBar slot — free-form */\n/* ------------------------------------------------------------------ */\n\nconst FilterBar = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]',\n // `grow` lets FilterBar absorb the free space; `min-w-0` lets the\n // QuickSearch slot inside shrink below its intrinsic width when the\n // toolbar runs `flex-nowrap` at `sm` and above, so the trailing\n // Actions cluster stays pinned on a single row.\n 'ds:grow ds:min-w-0',\n className ?? '',\n ]\n .join(' ')\n .trim()}\n {...props}\n >\n {children}\n </div>\n ),\n);\nFilterBar.displayName = 'DataTable.Toolbar.FilterBar';\n\n/* ------------------------------------------------------------------ */\n/* Actions slot — right-aligned via ms-auto */\n/* ------------------------------------------------------------------ */\n\nconst Actions = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={[\n 'ds:flex ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:ms-auto',\n className ?? '',\n ]\n .join(' ')\n .trim()}\n {...props}\n >\n {children}\n </div>\n ),\n);\nActions.displayName = 'DataTable.Toolbar.Actions';\n\n/* ------------------------------------------------------------------ */\n/* ExportCsv, ExportPdf, Print — icon-only buttons with tooltip labels */\n/* ------------------------------------------------------------------ */\n/* These three share the same shape: a single lucide icon, a localized\n * tooltip that doubles as the accessible label, and either a built-in\n * action (CSV / print) or a consumer-supplied handler (PDF). Rendered\n * as IconButton so a toolbar with several of them reads as a compact\n * icon group rather than three full-width labeled buttons. */\n\ntype ToolbarIconButtonProps = Omit<\n IconButtonProps,\n 'icon' | 'aria-label' | 'tooltip' | 'onClick'\n> & {\n /** Accessible label — becomes the tooltip text and `aria-label`. */\n label?: string;\n};\n\nexport interface ExportCsvProps extends ToolbarIconButtonProps {\n /** Optional override — receives the live AG Grid API. */\n onExport?: (api: GridApi) => void;\n}\n\nconst ExportCsv = forwardRef<HTMLButtonElement, ExportCsvProps>(\n ({ label, onExport, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ExportCsv');\n const handleClick = useCallback(() => {\n const api = getApi();\n if (!api) return;\n if (onExport) onExport(api);\n else api.exportDataAsCsv();\n }, [getApi, onExport]);\n\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<Download aria-hidden />}\n tooltip={label ?? t('dataTable.exportCsv')}\n onClick={handleClick}\n {...rest}\n />\n );\n },\n);\nExportCsv.displayName = 'DataTable.Toolbar.ExportCsv';\n\nexport interface ExportPdfProps extends ToolbarIconButtonProps {\n /**\n * Optional override for the default PDF generation. When omitted, clicking\n * the button calls the built-in handler (`defaultExportPdf`) which\n * dynamic-imports `jspdf` + `jspdf-autotable` and produces a paged PDF\n * of the current sort/filter state. Supply your own to plug in a\n * server-side PDF generator or a custom layout.\n */\n onClick?: (api: GridApi | undefined) => void;\n /** Filename for the generated PDF (default `data-table-export.pdf`). */\n fileName?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Default PDF handler — dynamic-imported so jspdf doesn't ship in */\n/* main bundle unless the user clicks Export PDF */\n/* ------------------------------------------------------------------ */\n\n// Resolve a DS HSL token to an `[r, g, b]` tuple by letting the browser do\n// the work. `--card` etc. are stored as raw `H S% L%` triplets — wrap in\n// `hsl(...)` and read back from a temp element's computed color. The\n// imperative `.style.*` mutation here is on a transient probe element\n// (never attached to JSX), permitted per src/docs/23-constraints.mdx\n// §Runtime-computed dimensions.\nfunction resolveTokenToRgb(\n varName: string,\n fallback: [number, number, number] = [30, 30, 30],\n): [number, number, number] {\n // SSR or unparseable computed color: return a neutral foreground RGB by\n // default so the PDF is at least legible — `[255, 255, 255]` would\n // produce white-on-white. Callers can override per-token (e.g. fill\n // tokens pass a light fallback, text tokens pass a dark one).\n if (typeof document === 'undefined') return fallback;\n const probe = document.createElement('span');\n probe.style.color = `hsl(var(${varName}))`;\n probe.style.position = 'absolute';\n probe.style.visibility = 'hidden';\n document.body.appendChild(probe);\n const computed = getComputedStyle(probe).color;\n document.body.removeChild(probe);\n const match = computed.match(/rgba?\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)/i);\n if (!match) return fallback;\n return [Number(match[1]), Number(match[2]), Number(match[3])];\n}\n\ninterface DefaultExportPdfOptions {\n fileName: string;\n}\n\n/**\n * Default Export PDF handler. Exported for tests and for consumers who want\n * to call it from a custom `onClick` (e.g. to add a logo or signature).\n */\nexport async function defaultExportPdf(\n api: GridApi | undefined,\n options: DefaultExportPdfOptions,\n): Promise<void> {\n if (!api) return;\n // Dynamic-imported so jspdf + jspdf-autotable stay out of consumers'\n // main bundles unless the user actually clicks Export PDF.\n const [{ jsPDF }, { default: autoTable }] = await Promise.all([\n import('jspdf'),\n import('jspdf-autotable'),\n ]);\n\n const columns = api.getColumns() ?? [];\n const visibleColumns = columns.filter((col) => col.isVisible());\n\n const head = [\n visibleColumns.map((col) => api.getDisplayNameForColumn(col, null) ?? ''),\n ];\n\n // Pull rows in current sort + filter order. AG Grid Community supports\n // forEachNodeAfterFilterAndSort on the client-side row model — the only\n // model this wrapper exposes.\n const body: string[][] = [];\n api.forEachNodeAfterFilterAndSort((node) => {\n if (!node.data) return;\n const cells = visibleColumns.map((col) => {\n const value = api.getCellValue({\n rowNode: node,\n colKey: col,\n useFormatter: true,\n });\n return value == null ? '' : String(value);\n });\n body.push(cells);\n });\n\n // Map DS tokens → RGB at handler runtime. `--card` backs the cell\n // background; `--muted` backs the header fill; `--card-foreground`\n // backs the body text and `--foreground` the header text. Per-token\n // fallbacks default fill tokens to a light grey and text tokens to a\n // dark grey, so SSR / token-resolution failure still produces a\n // legible PDF rather than white-on-white.\n const headerFill = resolveTokenToRgb('--muted', [240, 240, 240]);\n const headerText = resolveTokenToRgb('--foreground', [30, 30, 30]);\n const bodyText = resolveTokenToRgb('--card-foreground', [30, 30, 30]);\n const alternateFill = resolveTokenToRgb('--card', [250, 250, 250]);\n\n const doc = new jsPDF({ orientation: 'landscape' });\n autoTable(doc, {\n head,\n body,\n headStyles: { fillColor: headerFill, textColor: headerText },\n bodyStyles: { textColor: bodyText },\n alternateRowStyles: { fillColor: alternateFill },\n styles: {\n font: 'helvetica',\n fontSize: 10,\n cellPadding: 4,\n },\n });\n doc.save(options.fileName);\n}\n\nconst ExportPdf = forwardRef<HTMLButtonElement, ExportPdfProps>(\n ({ label, onClick, fileName, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ExportPdf');\n const handleClick = useCallback(() => {\n const api = getApi();\n if (onClick) {\n onClick(api);\n return;\n }\n // Fire-and-forget — errors bubble to the console for now; consumers\n // who need to surface them should supply their own `onClick`.\n void defaultExportPdf(api, {\n fileName: fileName ?? 'data-table-export.pdf',\n });\n }, [getApi, onClick, fileName]);\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<FileText aria-hidden />}\n tooltip={label ?? t('dataTable.exportPdf')}\n onClick={handleClick}\n {...rest}\n />\n );\n },\n);\nExportPdf.displayName = 'DataTable.Toolbar.ExportPdf';\n\nexport type PrintProps = ToolbarIconButtonProps;\n\nconst Print = forwardRef<HTMLButtonElement, PrintProps>(\n ({ label, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n const { onPrint } = useToolbarContext('DataTable.Toolbar.Print');\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<Printer aria-hidden />}\n tooltip={label ?? t('dataTable.print')}\n onClick={onPrint}\n {...rest}\n />\n );\n },\n);\nPrint.displayName = 'DataTable.Toolbar.Print';\n\n/* ------------------------------------------------------------------ */\n/* QuickSearch — `<TextInput size=\"sm\">` wired to AG Grid quickFilterText */\n/* ------------------------------------------------------------------ */\n\nexport interface QuickSearchProps {\n /** Placeholder text. Falls back to `t('dataTable.quickSearch.placeholder')`. */\n placeholder?: string;\n /** Debounce ms before pushing to AG Grid. Defaults to 150 ms. */\n debounceMs?: number;\n}\n\nconst QuickSearch = ({ placeholder, debounceMs = 150 }: QuickSearchProps) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.QuickSearch');\n const [value, setValue] = useState('');\n const timerRef = useRef<number | undefined>(undefined);\n\n useEffect(() => {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n timerRef.current = window.setTimeout(() => {\n const api = getApi();\n if (!api) return;\n // `setGridOption` is the public path in AG Grid v33+ for changing\n // any grid option after init.\n api.setGridOption('quickFilterText', value);\n }, debounceMs);\n return () => {\n if (timerRef.current) window.clearTimeout(timerRef.current);\n };\n }, [value, debounceMs, getApi]);\n\n return (\n // Slot wrapper caps the search at a sensible legible width on desktop —\n // without this, TextInput's `w-full` lets the QuickSearch absorb the\n // entire FilterBar row and push trailing Actions onto a second line at\n // 1024 / 1280 / 1440. `min-w-0` lets the slot shrink below `24rem` when\n // the toolbar is squeezed on narrow viewports. There is no\n // `--toolbar-search-max` token in the kit yet — see this component's\n // summary for a follow-up note recommending we add one.\n <div className=\"ds:w-full ds:max-w-[24rem] ds:min-w-0\">\n <TextInput\n type=\"search\"\n size=\"sm\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder={\n placeholder ?? t('dataTable.quickSearch.placeholder', 'Search…')\n }\n startAdornment={<Search aria-hidden className=\"ds:size-4\" />}\n clearable\n onClear={() => setValue('')}\n aria-label={t('dataTable.quickSearch.label', 'Quick search')}\n />\n </div>\n );\n};\nQuickSearch.displayName = 'DataTable.Toolbar.QuickSearch';\n\n/* ------------------------------------------------------------------ */\n/* Refresh — IconButton with a refresh glyph */\n/* ------------------------------------------------------------------ */\n\nexport interface RefreshButtonProps extends Omit<\n IconButtonProps,\n 'icon' | 'aria-label' | 'tooltip' | 'onClick'\n> {\n /** Called when the user clicks Refresh. */\n onRefresh: () => void;\n /** Accessible label. Falls back to `t('dataTable.refresh')`. */\n label?: string;\n}\n\nconst Refresh = forwardRef<HTMLButtonElement, RefreshButtonProps>(\n ({ onRefresh, label, intent = 'outline', ...rest }, ref) => {\n const { t } = useTranslation();\n return (\n <IconButton\n ref={ref}\n type=\"button\"\n intent={intent}\n icon={<RefreshCw aria-hidden />}\n tooltip={label ?? t('dataTable.refresh', 'Refresh')}\n onClick={onRefresh}\n {...rest}\n />\n );\n },\n);\nRefresh.displayName = 'DataTable.Toolbar.Refresh';\n\n/* ------------------------------------------------------------------ */\n/* FilterChips — chips for every active filter + clear-all */\n/* ------------------------------------------------------------------ */\n\ninterface ActiveFilterChip {\n colId: string;\n headerName: string;\n text: string;\n}\n\nfunction describeFilterModel(model: unknown): string {\n if (!model || typeof model !== 'object') return '';\n const m = model as Record<string, unknown>;\n // Text filter shape: { type, filter, filterTo, filterType }\n if (typeof m.filter === 'string' || typeof m.filter === 'number') {\n const type = typeof m.type === 'string' ? m.type : '';\n const filterTo =\n typeof m.filterTo === 'string' || typeof m.filterTo === 'number'\n ? String(m.filterTo)\n : '';\n if (type === 'inRange' && filterTo) {\n return `${m.filter} – ${filterTo}`;\n }\n return type ? `${type} ${m.filter}` : String(m.filter);\n }\n // Date filter shape: { type, dateFrom, dateTo }\n if (typeof m.dateFrom === 'string') {\n if (typeof m.dateTo === 'string' && m.dateTo) {\n return `${m.dateFrom} – ${m.dateTo}`;\n }\n return String(m.dateFrom);\n }\n // Set filter shape: { values: [...] }\n if (Array.isArray((m as { values?: unknown[] }).values)) {\n const values = (m as { values: unknown[] }).values;\n return values.map(String).join(', ');\n }\n return '';\n}\n\nconst FilterChips = () => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.FilterChips');\n const [chips, setChips] = useState<ActiveFilterChip[]>([]);\n const [quickFilter, setQuickFilter] = useState<string>('');\n\n const refresh = useCallback(() => {\n const api = getApi();\n if (!api) {\n setChips([]);\n setQuickFilter('');\n return;\n }\n const model = api.getFilterModel() ?? {};\n const cols = api.getColumns() ?? [];\n const next: ActiveFilterChip[] = [];\n for (const colId of Object.keys(model)) {\n const col = cols.find((c) => c.getColId() === colId);\n const headerName = api.getDisplayNameForColumn(col!, null) ?? colId;\n next.push({\n colId,\n headerName,\n text: describeFilterModel(model[colId]),\n });\n }\n setChips(next);\n const qf = api.getGridOption('quickFilterText');\n setQuickFilter(typeof qf === 'string' ? qf : '');\n }, [getApi]);\n\n // Subscribe to AG Grid filter-changed events. Use `addEventListener`\n // for the public subscription path (v33+ keeps this stable).\n useEffect(() => {\n const api = getApi();\n if (!api) return;\n const handler = (_event: FilterChangedEvent) => refresh();\n api.addEventListener('filterChanged', handler);\n refresh();\n return () => {\n api.removeEventListener('filterChanged', handler);\n };\n }, [getApi, refresh]);\n\n const total = chips.length + (quickFilter ? 1 : 0);\n if (total === 0) return null;\n\n function clearOne(colId: string) {\n const api = getApi();\n if (!api) return;\n api.destroyFilter(colId);\n }\n\n function clearAll() {\n const api = getApi();\n if (!api) return;\n api.setFilterModel(null);\n api.setGridOption('quickFilterText', '');\n setQuickFilter('');\n }\n\n return (\n <div\n role=\"group\"\n aria-label={t('dataTable.filterChips.label', 'Active filters')}\n className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {quickFilter && (\n <Tag\n label={`${t('dataTable.quickSearch.label', 'Quick search')}: ${quickFilter}`}\n size=\"sm\"\n fill=\"outline\"\n onRemove={() => {\n const api = getApi();\n api?.setGridOption('quickFilterText', '');\n setQuickFilter('');\n }}\n />\n )}\n {chips.map((c) => (\n <Tag\n key={c.colId}\n label={c.text ? `${c.headerName}: ${c.text}` : c.headerName}\n size=\"sm\"\n fill=\"outline\"\n onRemove={() => clearOne(c.colId)}\n />\n ))}\n <Button\n type=\"button\"\n intent=\"ghost\"\n size=\"sm\"\n onClick={clearAll}\n startIcon={<X aria-hidden className=\"ds:size-4\" />}\n >\n {t('dataTable.filterChips.clearAll', 'Clear all')}\n </Button>\n </div>\n );\n};\nFilterChips.displayName = 'DataTable.Toolbar.FilterChips';\n\n/* ------------------------------------------------------------------ */\n/* FacetFilter — pill-row column-scoped filter */\n/* ------------------------------------------------------------------ */\n\nexport interface FacetFilterOption<TValue = string> {\n value: TValue | null;\n label: string;\n}\n\nexport interface FacetFilterProps<TValue = string> {\n /** Column field to filter on. */\n field: string;\n /** Options shown as pills. `value: null` clears the filter. */\n options: FacetFilterOption<TValue>[];\n /** Accessible label for the pill group. */\n label?: string;\n}\n\nconst FacetFilter = <TValue extends string | number | boolean = string>({\n field,\n options,\n label,\n}: FacetFilterProps<TValue>) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.FacetFilter');\n const [active, setActive] = useState<TValue | null>(null);\n\n function apply(value: TValue | null) {\n setActive(value);\n const api = getApi();\n if (!api) return;\n if (value === null) {\n api.destroyFilter(field);\n return;\n }\n // Use the column filter API directly — AG Grid Community supports\n // setColumnFilterModel for the built-in filter on a column.\n api.setColumnFilterModel(field, {\n type: 'equals',\n filter: value,\n });\n api.onFilterChanged();\n }\n\n return (\n <div\n role=\"group\"\n aria-label={label ?? t('dataTable.facetFilter.label', 'Filter')}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n {options.map((opt) => {\n const isActive = active === opt.value;\n return (\n <Button\n key={String(opt.value)}\n type=\"button\"\n size=\"sm\"\n intent={isActive ? 'primary' : 'secondary'}\n aria-pressed={isActive}\n onClick={() => apply(opt.value)}\n >\n {opt.label}\n </Button>\n );\n })}\n </div>\n );\n};\n(FacetFilter as { displayName?: string }).displayName =\n 'DataTable.Toolbar.FacetFilter';\n\n/* ------------------------------------------------------------------ */\n/* ExportMenu — compound: CSV (always), Excel (xlsx), PDF, custom */\n/* ------------------------------------------------------------------ */\n\nexport type ExportFormat = 'csv' | 'xlsx' | 'pdf' | 'custom';\n\nexport interface ExportMenuItemProps {\n /** Built-in format or `custom` for consumer-supplied handler. */\n format: ExportFormat;\n /** Label override. Built-in formats default to `t('dataTable.export.{format}')`. */\n label?: string;\n /** Consumer handler — required for `format: 'custom'`. */\n onClick?: (api: GridApi | undefined) => void;\n /** File-name override (only used by built-in formats). */\n fileName?: string;\n}\n\nconst DEFAULT_EXPORT_ITEMS: ExportFormat[] = ['csv', 'xlsx', 'pdf'];\n\nasync function defaultExportXlsx(\n api: GridApi | undefined,\n options: { fileName: string },\n): Promise<void> {\n if (!api) return;\n // Dynamic-imported so exceljs stays out of consumers' main bundles\n // unless the user actually clicks Excel export.\n const ExcelJS = await import('exceljs');\n const workbook = new ExcelJS.Workbook();\n const sheet = workbook.addWorksheet('Sheet1');\n\n const columns = api.getColumns() ?? [];\n const visibleColumns = columns.filter((col) => col.isVisible());\n\n sheet.addRow(\n visibleColumns.map(\n (col) => api.getDisplayNameForColumn(col, null) ?? col.getColId(),\n ),\n );\n\n api.forEachNodeAfterFilterAndSort((node) => {\n if (!node.data) return;\n sheet.addRow(\n visibleColumns.map((col) => {\n const value = api.getCellValue({\n rowNode: node,\n colKey: col,\n useFormatter: true,\n });\n return value == null ? '' : value;\n }),\n );\n });\n\n // Header row uses DS tokens resolved at runtime — same approach as\n // defaultExportPdf above.\n const headerFill = resolveTokenToRgb('--muted', [240, 240, 240]);\n const headerText = resolveTokenToRgb('--foreground', [30, 30, 30]);\n const headerRow = sheet.getRow(1);\n const hex = ([r, g, b]: [number, number, number]) =>\n `${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b\n .toString(16)\n .padStart(2, '0')}`.toUpperCase();\n headerRow.eachCell((cell: import('exceljs').Cell) => {\n cell.font = { bold: true, color: { argb: `FF${hex(headerText)}` } };\n cell.fill = {\n type: 'pattern',\n pattern: 'solid',\n fgColor: { argb: `FF${hex(headerFill)}` },\n };\n });\n\n const buffer = await workbook.xlsx.writeBuffer();\n const blob = new Blob([buffer], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = options.fileName;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n}\n\ninterface ExportMenuContextValue {\n /** AG Grid API resolver (forwarded to each item). */\n getApi: () => GridApi | undefined;\n}\n\nconst ExportMenuContext = createContext<ExportMenuContextValue | null>(null);\n\nfunction useExportMenuContext(): ExportMenuContextValue {\n const ctx = useContext(ExportMenuContext);\n if (!ctx) {\n throw new Error(\n 'DataTable.Toolbar.ExportMenu.Item must be rendered inside DataTable.Toolbar.ExportMenu.',\n );\n }\n return ctx;\n}\n\nexport interface ExportMenuProps {\n /** Custom menu items. When omitted, renders the default CSV+Excel+PDF trio. */\n children?: ReactNode;\n /** Accessible label for the trigger. */\n label?: string;\n}\n\nconst ExportMenu = ({ children, label }: ExportMenuProps) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ExportMenu');\n const value = useMemo(() => ({ getApi }), [getApi]);\n const itemsContent =\n children ??\n DEFAULT_EXPORT_ITEMS.map((f) => <ExportMenuItem key={f} format={f} />);\n return (\n <ExportMenuContext.Provider value={value}>\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <IconButton\n type=\"button\"\n intent=\"outline\"\n icon={<Download aria-hidden />}\n tooltip={label ?? t('dataTable.export.menu', 'Export')}\n aria-label={label ?? t('dataTable.export.menu', 'Export')}\n aria-haspopup=\"menu\"\n />\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\" sideOffset={4}>\n {itemsContent}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </ExportMenuContext.Provider>\n );\n};\nExportMenu.displayName = 'DataTable.Toolbar.ExportMenu';\n\nfunction defaultLabel(\n t: (key: string, fallback: string) => string,\n format: ExportFormat,\n): string {\n if (format === 'csv') return t('dataTable.export.csv', 'Export CSV');\n if (format === 'xlsx') return t('dataTable.export.xlsx', 'Export Excel');\n if (format === 'pdf') return t('dataTable.export.pdf', 'Export PDF');\n return t('dataTable.export.custom', 'Export');\n}\n\nfunction defaultIcon(format: ExportFormat): ReactNode {\n if (format === 'csv') return <Download aria-hidden className=\"ds:size-4\" />;\n if (format === 'xlsx')\n return <FileSpreadsheet aria-hidden className=\"ds:size-4\" />;\n if (format === 'pdf') return <FileText aria-hidden className=\"ds:size-4\" />;\n return <Download aria-hidden className=\"ds:size-4\" />;\n}\n\nconst ExportMenuItem = ({\n format,\n label,\n onClick,\n fileName,\n}: ExportMenuItemProps) => {\n const { t } = useTranslation();\n const { getApi } = useExportMenuContext();\n const handleClick = useCallback(() => {\n const api = getApi();\n if (format === 'csv') {\n api?.exportDataAsCsv();\n return;\n }\n if (format === 'pdf') {\n void defaultExportPdf(api, {\n fileName: fileName ?? 'data-table-export.pdf',\n });\n return;\n }\n if (format === 'xlsx') {\n void defaultExportXlsx(api, {\n fileName: fileName ?? 'data-table-export.xlsx',\n });\n return;\n }\n // custom — consumer is required to handle.\n onClick?.(api);\n }, [format, fileName, onClick, getApi]);\n\n return (\n <DropdownMenu.Item onSelect={handleClick}>\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n {defaultIcon(format)}\n <span>{label ?? defaultLabel(t, format)}</span>\n </span>\n </DropdownMenu.Item>\n );\n};\nExportMenuItem.displayName = 'DataTable.Toolbar.ExportMenu.Item';\n\n/* ------------------------------------------------------------------ */\n/* ColumnToggle — popover with a checkbox per column */\n/* ------------------------------------------------------------------ */\n\ninterface ColumnEntry {\n colId: string;\n displayName: string;\n visible: boolean;\n}\n\nfunction readColumnEntries(api: GridApi | undefined): ColumnEntry[] {\n if (!api) return [];\n const columns = api.getColumns() ?? [];\n return columns\n .map((col) => {\n const def = col.getColDef();\n if (def.hide === undefined && col.getColId().startsWith('ag-Grid-'))\n return null;\n return {\n colId: col.getColId(),\n displayName: api.getDisplayNameForColumn(col, null) || col.getColId(),\n visible: col.isVisible(),\n };\n })\n .filter((c): c is ColumnEntry => c !== null);\n}\n\nexport interface ColumnToggleProps {\n label?: string;\n}\n\nconst ColumnToggle = ({ label }: ColumnToggleProps) => {\n const { t } = useTranslation();\n const { getApi } = useToolbarContext('DataTable.Toolbar.ColumnToggle');\n const [open, setOpen] = useState(false);\n const [columns, setColumns] = useState<ColumnEntry[]>([]);\n const [draggingColId, setDraggingColId] = useState<string | null>(null);\n const [dragOverColId, setDragOverColId] = useState<string | null>(null);\n\n // Refresh the column list whenever the popover opens — picks up\n // columns that were added/removed/renamed since last open.\n useEffect(() => {\n if (!open) return;\n setColumns(readColumnEntries(getApi()));\n }, [open, getApi]);\n\n const toggleColumn = useCallback(\n (colId: string, nextVisible: boolean) => {\n const api = getApi();\n if (!api) return;\n api.setColumnsVisible([colId], nextVisible);\n setColumns((prev) =>\n prev.map((c) =>\n c.colId === colId ? { ...c, visible: nextVisible } : c,\n ),\n );\n },\n [getApi],\n );\n\n // Reorder local list AND forward the move to AG Grid so the grid's\n // column order tracks the popover. `api.moveColumns([id], toIndex)`\n // does both the data move and the display refresh in v33+.\n const moveColumn = useCallback(\n (fromColId: string, toColId: string) => {\n if (fromColId === toColId) return;\n const api = getApi();\n if (!api) return;\n setColumns((prev) => {\n const fromIdx = prev.findIndex((c) => c.colId === fromColId);\n const toIdx = prev.findIndex((c) => c.colId === toColId);\n if (fromIdx < 0 || toIdx < 0) return prev;\n const next = [...prev];\n const [moved] = next.splice(fromIdx, 1);\n next.splice(toIdx, 0, moved);\n return next;\n });\n const toIdx = columns.findIndex((c) => c.colId === toColId);\n if (toIdx >= 0) api.moveColumns([fromColId], toIdx);\n },\n [getApi, columns],\n );\n\n const labelText = label ?? t('dataTable.columnToggle');\n\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>\n <IconButton\n type=\"button\"\n intent=\"outline\"\n icon={<Columns aria-hidden />}\n aria-label={labelText}\n aria-haspopup=\"dialog\"\n />\n </Popover.Trigger>\n <Popover.Content size=\"sm\" align=\"end\">\n <Popover.Heading>{labelText}</Popover.Heading>\n <ul\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n aria-label={labelText}\n >\n {columns.map((c) => {\n const isDragging = draggingColId === c.colId;\n const isDragOver =\n dragOverColId === c.colId && draggingColId !== c.colId;\n return (\n <li\n key={c.colId}\n draggable\n onDragStart={(e) => {\n setDraggingColId(c.colId);\n e.dataTransfer.effectAllowed = 'move';\n e.dataTransfer.setData('text/plain', c.colId);\n }}\n onDragOver={(e) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n setDragOverColId(c.colId);\n }}\n onDragLeave={() => {\n setDragOverColId((prev) => (prev === c.colId ? null : prev));\n }}\n onDrop={(e) => {\n e.preventDefault();\n const fromColId = e.dataTransfer.getData('text/plain');\n if (fromColId) moveColumn(fromColId, c.colId);\n setDraggingColId(null);\n setDragOverColId(null);\n }}\n onDragEnd={() => {\n setDraggingColId(null);\n setDragOverColId(null);\n }}\n className={[\n 'ds:flex ds:items-center ds:gap-[var(--spacing-xs)] ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-xs)] ds:py-[var(--spacing-2xs,var(--spacing-xs))] ds:transition-colors',\n isDragging ? 'ds:opacity-50' : '',\n isDragOver\n ? 'ds:bg-[color:color-mix(in_srgb,var(--primary)_8%,transparent)]'\n : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:cursor-grab ds:text-[color:var(--muted-foreground)] ds:active:cursor-grabbing\"\n >\n <GripVertical className=\"ds:size-4\" />\n </span>\n <Checkbox\n label={c.displayName}\n checked={c.visible}\n onCheckedChange={(checked) =>\n toggleColumn(c.colId, checked === true)\n }\n />\n </li>\n );\n })}\n </ul>\n </Popover.Content>\n </Popover.Root>\n );\n};\nColumnToggle.displayName = 'DataTable.Toolbar.ColumnToggle';\n\n/* ------------------------------------------------------------------ */\n/* BulkAction — hidden when no rows are selected */\n/* ------------------------------------------------------------------ */\n\nexport interface BulkActionProps extends Omit<\n ButtonProps,\n 'onClick' | 'children' | 'startIcon' | 'intent'\n> {\n label: string;\n icon?: ReactNode;\n onClick: (api: GridApi | undefined) => void;\n variant?: 'default' | 'destructive';\n}\n\nconst BulkAction = forwardRef<HTMLButtonElement, BulkActionProps>(\n (\n { label, icon, onClick, variant = 'default', size = 'sm', ...rest },\n ref,\n ) => {\n const { t } = useTranslation();\n const { getApi, selectionCount } = useToolbarContext(\n 'DataTable.Toolbar.BulkAction',\n );\n if (selectionCount === 0) return null;\n\n const resolvedIntent =\n variant === 'destructive' ? 'destructive' : 'secondary';\n\n return (\n <Button\n ref={ref}\n type=\"button\"\n intent={resolvedIntent}\n size={size}\n startIcon={sizeIcon(icon)}\n onClick={() => onClick(getApi())}\n aria-label={`${label} (${t('dataTable.bulkAction', { count: selectionCount })})`}\n {...rest}\n >\n <span>{label}</span>\n <span\n aria-hidden=\"true\"\n className=\"ds:ms-[var(--spacing-xs)] ds:opacity-80\"\n >\n {t('dataTable.bulkAction', { count: selectionCount })}\n </span>\n </Button>\n );\n },\n);\nBulkAction.displayName = 'DataTable.Toolbar.BulkAction';\n\n/* ------------------------------------------------------------------ */\n/* Assembled namespace — mounted on DataTable.Toolbar downstream */\n/* ------------------------------------------------------------------ */\n\nconst ExportMenuNamespace = Object.assign(ExportMenu, {\n Item: ExportMenuItem,\n});\n\nexport const Toolbar = Object.assign(ToolbarRoot, {\n FilterBar,\n Actions,\n /** @deprecated Use `Toolbar.ExportMenu` with a `csv` item. */\n ExportCsv,\n /** @deprecated Use `Toolbar.ExportMenu` with a `pdf` item. */\n ExportPdf,\n Print,\n ColumnToggle,\n BulkAction,\n QuickSearch,\n Refresh,\n FilterChips,\n FacetFilter,\n ExportMenu: ExportMenuNamespace,\n});\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport i18next from 'i18next';\nimport { Search, X } from 'lucide-react';\nimport { TextInput } from '../../text-input';\nimport { Select, type SelectOption } from '../../select';\nimport { Button } from '../../button';\n\n/**\n * Custom AG Grid filter component — text-comparison filter.\n *\n * Fills the gap left by `agTextColumnFilter`'s stock browser-skinned\n * input by wrapping the kit's `<TextInput>` and `<Select>` so the\n * column-header menu (`TextFilter`) and the inline floating row\n * (`TextFloatingFilter`) match the DS form language.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'description',\n * filter: TextFilter,\n * floatingFilter: true,\n * floatingFilterComponent: TextFloatingFilter,\n * filterParams: { defaultOperator: 'contains' },\n * }\n * ```\n *\n * Model shape `{ type, filter }` mirrors AG Grid's `agTextColumnFilter`\n * text-operator vocabulary (`contains`, `equals`, `startsWith`,\n * `endsWith`, `notContains`) so server-side adapters that already\n * understand the stock filter can read this one identically.\n */\n\nexport type TextFilterOperator =\n | 'contains'\n | 'equals'\n | 'startsWith'\n | 'endsWith'\n | 'notContains';\n\nexport interface TextFilterModel {\n type: TextFilterOperator;\n filter: string;\n}\n\nexport interface TextFilterParams {\n placeholder?: string;\n defaultOperator?: TextFilterOperator;\n}\n\nconst OPERATORS: TextFilterOperator[] = [\n 'contains',\n 'equals',\n 'startsWith',\n 'endsWith',\n 'notContains',\n];\n\n// Accent-folded, case-insensitive comparison. Intl.Collator handles\n// locale-aware diacritic stripping (e.g. \"città\" ~ \"citta\") so users\n// don't need to type accented characters exactly to find rows.\nfunction makeMatcher(locale: string) {\n const collator = new Intl.Collator(locale, {\n sensitivity: 'base',\n usage: 'search',\n });\n\n // Intl.Collator.compare returns 0 only on full-string equality (under\n // sensitivity:base). For substring tests we slice and compare windows.\n function indexOf(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n if (needle.length > haystack.length) return -1;\n for (let i = 0; i <= haystack.length - needle.length; i += 1) {\n if (\n collator.compare(haystack.slice(i, i + needle.length), needle) === 0\n ) {\n return i;\n }\n }\n return -1;\n }\n\n return {\n equals: (a: string, b: string) => collator.compare(a, b) === 0,\n contains: (haystack: string, needle: string) =>\n indexOf(haystack, needle) !== -1,\n startsWith: (haystack: string, needle: string) =>\n needle.length <= haystack.length &&\n collator.compare(haystack.slice(0, needle.length), needle) === 0,\n endsWith: (haystack: string, needle: string) =>\n needle.length <= haystack.length &&\n collator.compare(\n haystack.slice(haystack.length - needle.length),\n needle,\n ) === 0,\n };\n}\n\nfunction coerceToString(raw: unknown): string | null {\n if (raw === null || raw === undefined) return null;\n return typeof raw === 'string' ? raw : String(raw);\n}\n\nexport function TextFilter(\n props: CustomFilterProps<unknown, unknown, TextFilterModel> &\n TextFilterParams,\n) {\n const { model, onModelChange, getValue, placeholder, defaultOperator } =\n props;\n const { t } = useTranslation('ui');\n\n const initialOperator: TextFilterOperator =\n model?.type ?? defaultOperator ?? 'contains';\n const [operator, setOperator] = useState<TextFilterOperator>(initialOperator);\n const [draft, setDraft] = useState<string>(model?.filter ?? '');\n\n // Hydrate local state when AG Grid pushes an external model change\n // (e.g. consumer calls api.setFilterModel programmatically).\n useEffect(() => {\n setOperator(model?.type ?? defaultOperator ?? 'contains');\n setDraft(model?.filter ?? '');\n }, [model, defaultOperator]);\n\n const matcher = useMemo(() => makeMatcher(i18next.language), []);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const active = model;\n if (!active || active.filter === '') return true;\n const value = coerceToString(getValue(params.node));\n if (value === null) return false;\n switch (active.type) {\n case 'equals':\n return matcher.equals(value, active.filter);\n case 'contains':\n return matcher.contains(value, active.filter);\n case 'startsWith':\n return matcher.startsWith(value, active.filter);\n case 'endsWith':\n return matcher.endsWith(value, active.filter);\n case 'notContains':\n return !matcher.contains(value, active.filter);\n default:\n return true;\n }\n },\n });\n\n function apply() {\n const trimmed = draft.trim();\n if (trimmed === '') {\n onModelChange(null);\n return;\n }\n onModelChange({ type: operator, filter: draft });\n }\n\n function clear() {\n setDraft('');\n setOperator(defaultOperator ?? 'contains');\n onModelChange(null);\n }\n\n const operatorOptions: SelectOption<TextFilterOperator>[] = OPERATORS.map(\n (op) => ({\n value: op,\n label: t(`dataTable.textFilter.operators.${op}`),\n }),\n );\n\n const placeholderLabel = placeholder ?? t('dataTable.textFilter.placeholder');\n\n return (\n <div\n data-component=\"text-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Select<TextFilterOperator>\n size=\"sm\"\n options={operatorOptions}\n value={operator}\n onValueChange={(next) => {\n if (next === '') return;\n setOperator(next);\n }}\n aria-label={t('dataTable.textFilter.operators.contains')}\n />\n <TextInput\n size=\"sm\"\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n apply();\n }\n }}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n startAdornment={<Search aria-hidden=\"true\" className=\"ds:size-4\" />}\n />\n <div className=\"ds:flex ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.textFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.textFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `TextFilter`.\n *\n * Renders a `<TextInput size=\"sm\">` directly as the inline floating\n * filter — leading search icon, optional trailing clear button, fixed\n * operator (the popover version owns operator selection so the inline\n * row stays compact).\n *\n * Commits debounce at 200ms; empty input commits `null` so the grid\n * stops filtering as soon as the field is blank.\n */\nexport function TextFloatingFilter(\n props: CustomFloatingFilterProps<IFilter, unknown, unknown, TextFilterModel>,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as TextFilterParams | undefined) ?? {};\n const defaultOperator: TextFilterOperator =\n filterParams.defaultOperator ?? 'contains';\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.textFilter.placeholder');\n\n const [draft, setDraft] = useState<string>(model?.filter ?? '');\n\n // Hydrate when the model changes externally (programmatic reset).\n useEffect(() => {\n setDraft(model?.filter ?? '');\n }, [model?.filter]);\n\n // Debounced commit. Avoids hammering AG Grid with a model push on\n // every keystroke; 200ms matches the kit's other deferred-input\n // patterns. A bare setTimeout + cleanup is sufficient — no third-party\n // debounce hook required.\n useEffect(() => {\n // Avoid spurious commits when the local draft already matches the\n // applied model (e.g. just-hydrated initial mount).\n if (draft === (model?.filter ?? '')) return;\n\n const timer = setTimeout(() => {\n if (draft === '') {\n if (model) onModelChange(null);\n return;\n }\n onModelChange({ type: defaultOperator, filter: draft });\n }, 200);\n\n return () => clearTimeout(timer);\n }, [draft, defaultOperator, model, onModelChange]);\n\n function clearImmediate() {\n setDraft('');\n if (model) onModelChange(null);\n }\n\n return (\n <div data-component=\"text-floating-filter\" className=\"ds:w-full\">\n <TextInput\n size=\"sm\"\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n startAdornment={<Search aria-hidden=\"true\" className=\"ds:size-4\" />}\n endAdornment={\n draft.length > 0 ? (\n <button\n type=\"button\"\n aria-label={t('dataTable.textFilter.clear')}\n onClick={clearImmediate}\n className=\"ds:pointer-events-auto ds:flex ds:items-center ds:text-[var(--muted-foreground)] ds:hover:text-[var(--foreground)] ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none\"\n >\n <X aria-hidden=\"true\" className=\"ds:size-4\" />\n </button>\n ) : undefined\n }\n />\n </div>\n );\n}\n","/* -------------------------------------------------------------------- */\n/* Agent adapter — DataTable. */\n/* */\n/* Operations work against the curated `DataTableHandle`, never the raw */\n/* ag-grid `GridApi` (consumers needing the raw API call `getRawApi()`). */\n/* See `src/docs/26-agent-readiness.mdx` §15. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { DataTableHandle, DataTableSortEntry } from './data-table';\n\nexport const dataTableAgent: AgentAdapter<DataTableHandle> = {\n id: 'data-table',\n capabilities: [\n 'select_single',\n 'select_multiple',\n 'range_pick',\n 'filter',\n 'sort',\n 'paginate',\n ],\n state: {\n selection: {\n type: 'string[]',\n descriptionKey: 'ui.agent.dataTable.state.selection',\n description: 'Row ids of currently-selected rows.',\n read: (handle) => handle.getSelection(),\n },\n filter: {\n type: 'object',\n descriptionKey: 'ui.agent.dataTable.state.filter',\n description: 'Current ag-grid filter model, keyed by column id.',\n read: (handle) => handle.getFilter(),\n },\n sort: {\n type: 'Array<{ colId, sort }>',\n descriptionKey: 'ui.agent.dataTable.state.sort',\n description: 'Active sort, in priority order.',\n read: (handle) => handle.getSort(),\n },\n currentPage: {\n type: 'number',\n descriptionKey: 'ui.agent.dataTable.state.currentPage',\n description: 'Zero-indexed page number.',\n read: (handle) => handle.getCurrentPage(),\n },\n },\n actions: {\n select_rows: {\n safety: 'read',\n argsType: '{ ids: string[] }',\n descriptionKey: 'ui.agent.dataTable.actions.selectRows',\n description: 'Replace the current selection with the given row ids.',\n invoke: (handle, args: { ids: string[] }) => {\n handle.setSelection(args.ids);\n },\n },\n select_range: {\n safety: 'read',\n argsType: '{ fromId: string, toId: string }',\n descriptionKey: 'ui.agent.dataTable.actions.selectRange',\n description:\n 'Select every row between fromId and toId, inclusive, in current sort order.',\n invoke: (handle, args: { fromId: string; toId: string }) => {\n handle.selectRange(args.fromId, args.toId);\n },\n },\n clear_selection: {\n safety: 'read',\n descriptionKey: 'ui.agent.dataTable.actions.clearSelection',\n description: 'Deselect all rows.',\n invoke: (handle) => {\n handle.clearSelection();\n },\n },\n apply_filter: {\n safety: 'read',\n argsType: '{ model: Record<string, unknown> }',\n descriptionKey: 'ui.agent.dataTable.actions.applyFilter',\n description: 'Replace the filter model with the given object.',\n invoke: (handle, args: { model: Record<string, unknown> }) => {\n handle.setFilter(args.model);\n },\n },\n sort_by: {\n safety: 'read',\n argsType: '{ model: DataTableSortEntry[] }',\n descriptionKey: 'ui.agent.dataTable.actions.sortBy',\n description:\n 'Replace the active sort with the given list (priority order).',\n invoke: (handle, args: { model: DataTableSortEntry[] }) => {\n handle.setSort(args.model);\n },\n },\n go_to_page: {\n safety: 'read',\n argsType: '{ page: number }',\n descriptionKey: 'ui.agent.dataTable.actions.goToPage',\n description: 'Navigate to the given zero-indexed page.',\n invoke: (handle, args: { page: number }) => {\n handle.goToPage(args.page);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'data-table',\n description: 'Marks the DataTable wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'gridId',\n description:\n 'Sourced from the gridId prop. Required to address a specific table from the agent.',\n },\n item: {\n attr: 'row-id',\n description:\n 'Native ag-grid row-id attribute on each rendered row. Selection is performed via the curated handle, not by DOM mutation.',\n },\n },\n};\n","import 'ag-grid-community/styles/ag-grid.css';\n// Font-only — `@font-face { agGridQuartz }` for the icon glyphs. We\n// deliberately do NOT import `ag-theme-quartz.css`: that file scopes ~90\n// CSS variables to `.ag-theme-quartz` and hardcodes colors / IBM Plex Sans\n// / 8px grid, which fight the design-system tokens. `ag-grid-theme.css`\n// below is a standalone bridge that defines every var AG Grid references,\n// mapped to DS tokens.\nimport 'ag-grid-community/styles/agGridQuartzFont.css';\nimport '../../tokens/ag-grid-theme.css';\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode,\n} from 'react';\nimport { Skeleton } from '../skeleton';\nimport { EmptyState } from '../empty-state';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { AgGridReact } from 'ag-grid-react';\nimport {\n AllCommunityModule,\n ModuleRegistry,\n type ColDef,\n type ColGroupDef,\n type FilterChangedEvent,\n type GridApi,\n type GridOptions,\n type RowClassParams,\n type SortChangedEvent,\n} from 'ag-grid-community';\nimport { Toolbar, ToolbarProvider } from './toolbar';\nimport { TextFilter, TextFloatingFilter } from './filters/text-filter';\nimport { useAgentRegistration } from '../../agent';\nimport { usePrefersReducedMotion, useTheme } from '../../hooks';\nimport { dataTableAgent } from './data-table.agent';\n\n// AG Grid v33+ requires module registration before any grid renders.\nModuleRegistry.registerModules([AllCommunityModule]);\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst dataTableVariants = cva('ag-theme-alfadocs ds:w-full', {\n variants: {\n density: {\n default: '',\n compact: 'data-table-compact',\n expanded: 'data-table-expanded',\n },\n bordered: {\n true: '',\n false: 'ds:[--ag-borders:none]',\n },\n },\n defaultVariants: {\n density: 'default',\n bordered: true,\n },\n});\n\n/* ------------------------------------------------------------------ */\n/* Curated imperative handle — agent-readiness contract */\n/* ------------------------------------------------------------------ */\n\nexport interface DataTableSortEntry {\n colId: string;\n sort: 'asc' | 'desc';\n}\n\n/**\n * Curated handle exposed via `forwardRef`. Replaces the legacy raw `GridApi`\n * forwarding — see `src/docs/26-agent-readiness.mdx` §15. Consumers needing\n * the unwrapped ag-grid API call `getRawApi()`.\n */\nexport interface DataTableHandle<TData = unknown> {\n getSelection: () => string[];\n setSelection: (ids: string[]) => void;\n selectRange: (fromId: string, toId: string) => void;\n clearSelection: () => void;\n getFilter: () => Record<string, unknown>;\n setFilter: (model: Record<string, unknown>) => void;\n getSort: () => DataTableSortEntry[];\n setSort: (model: DataTableSortEntry[]) => void;\n getCurrentPage: () => number;\n goToPage: (page: number) => void;\n getRawApi: () => GridApi<TData> | undefined;\n}\n\n/* ------------------------------------------------------------------ */\n/* Props */\n/* ------------------------------------------------------------------ */\n\nexport interface DataTableProps<TData = unknown> extends Omit<\n VariantProps<typeof dataTableVariants>,\n 'density'\n> {\n /**\n * Column definitions — accepts a mix of leaf `ColDef`s and header\n * `ColGroupDef`s (for two-row grouped headers via `children: [...]`).\n */\n columnDefs: (ColDef<TData> | ColGroupDef<TData>)[];\n rowData?: TData[];\n rowSelection?: 'single' | 'multiple';\n pagination?: boolean;\n paginationPageSize?: number;\n /**\n * Page-size dropdown options shown in the AG Grid pagination panel.\n * Pass `false` to hide the dropdown entirely. Default: `[10, 25, 50, 100]`.\n */\n paginationPageSizeSelector?: number[] | false;\n gridId?: string;\n onSelectionChanged?: (rows: TData[]) => void;\n onSortChanged?: (event: SortChangedEvent<TData>) => void;\n onFilterChanged?: (event: FilterChangedEvent<TData>) => void;\n noRowsOverlay?: ComponentType;\n loadingOverlay?: ComponentType;\n gridOptions?: GridOptions<TData>;\n /** Grid height as a Tailwind height class, e.g. `\"h-[500px]\"` or `\"h-[var(--data-table-height)]\"` */\n heightClass?: string;\n className?: string;\n\n /** Row height preset. `expanded` adds headroom for complex cells (balances, tag lists). */\n density?: 'compact' | 'default' | 'expanded';\n\n /** Map row → class name. Use together with `data-table-row-success/warning/error` for tinted rows. */\n getRowClass?: (params: RowClassParams<TData>) => string | undefined;\n /** Rows pinned at the bottom of the grid. Use `useTotalRow()` to compute a totals row. */\n pinnedBottomRowData?: TData[];\n\n /** Print-optimised mode — hides toolbar, disables pagination, renders every row. */\n printMode?: boolean;\n\n /** Composable toolbar — renders `<DataTable.Toolbar>…</DataTable.Toolbar>` above the grid. */\n children?: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Locale text builder */\n/* ------------------------------------------------------------------ */\n\nfunction useAgLocaleText() {\n const { t } = useTranslation();\n return useMemo(\n () => ({\n // Filter strings\n contains: t('dataTable.agGrid.contains'),\n notContains: t('dataTable.agGrid.notContains'),\n equals: t('dataTable.agGrid.equals'),\n notEqual: t('dataTable.agGrid.notEqual'),\n startsWith: t('dataTable.agGrid.startsWith'),\n endsWith: t('dataTable.agGrid.endsWith'),\n lessThan: t('dataTable.agGrid.lessThan'),\n greaterThan: t('dataTable.agGrid.greaterThan'),\n inRange: t('dataTable.agGrid.inRange'),\n blank: t('dataTable.agGrid.blank'),\n notBlank: t('dataTable.agGrid.notBlank'),\n filterOoo: t('dataTable.agGrid.filterOoo'),\n applyFilter: t('dataTable.agGrid.applyFilter'),\n resetFilter: t('dataTable.agGrid.resetFilter'),\n noRowsToShow: t('dataTable.agGrid.noRowsToShow'),\n selectAll: t('dataTable.agGrid.selectAll'),\n // Pagination\n page: t('dataTable.page'),\n of: t('dataTable.of'),\n to: t('dataTable.to'),\n nextPage: t('dataTable.nextPage'),\n previousPage: t('dataTable.previousPage'),\n firstPage: t('dataTable.firstPage'),\n lastPage: t('dataTable.lastPage'),\n pageSize: t('dataTable.pageSize'),\n }),\n\n [t],\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Loading overlay */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultLoadingOverlay() {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:w-full ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-md)]\"\n >\n {Array.from({ length: 5 }).map((_, i) => (\n <Skeleton\n key={i}\n variant=\"rectangular\"\n className=\"ds:h-[var(--min-target-size)] ds:w-full\"\n />\n ))}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* No-rows overlay — wired to the DS EmptyState component */\n/* ------------------------------------------------------------------ */\n\nfunction DefaultNoRowsOverlay() {\n const { t } = useTranslation();\n return (\n <EmptyState\n variant=\"no-results\"\n size=\"sm\"\n title={t('dataTable.noRows')}\n description={t('dataTable.noRowsDescription')}\n />\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Column persistence helpers */\n/* ------------------------------------------------------------------ */\n\nfunction loadColumnState(gridId: string) {\n try {\n const raw = localStorage.getItem(`data-table-col-state:${gridId}`);\n return raw ? JSON.parse(raw) : null;\n } catch {\n return null;\n }\n}\n\nfunction saveColumnState(gridId: string, api: GridApi) {\n try {\n localStorage.setItem(\n `data-table-col-state:${gridId}`,\n JSON.stringify(api.getColumnState()),\n );\n } catch {\n // localStorage may be unavailable in some environments\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* DataTable */\n/* ------------------------------------------------------------------ */\n\nfunction DataTableInner<TData = unknown>(\n props: DataTableProps<TData>,\n ref: React.ForwardedRef<DataTableHandle<TData>>,\n) {\n const {\n columnDefs,\n rowData,\n rowSelection,\n pagination = false,\n paginationPageSize = 25,\n paginationPageSizeSelector = [10, 25, 50, 100],\n gridId,\n onSelectionChanged,\n onSortChanged,\n onFilterChanged,\n noRowsOverlay,\n loadingOverlay,\n gridOptions,\n density,\n bordered,\n heightClass = 'ds:h-[500px]',\n className,\n getRowClass,\n pinnedBottomRowData,\n printMode = false,\n children,\n } = props;\n\n const { t, i18n } = useTranslation();\n const agGridRef = useRef<AgGridReact<TData>>(null);\n const [selectionCount, setSelectionCount] = useState(0);\n const [sortAnnouncement, setSortAnnouncement] = useState('');\n const localeText = useAgLocaleText();\n\n // Curated imperative handle — see DataTableHandle above.\n const handle = useMemo<DataTableHandle<TData>>(\n () => ({\n getSelection: () => {\n const api = agGridRef.current?.api;\n if (!api) return [];\n const ids: string[] = [];\n for (const node of api.getSelectedNodes()) {\n if (node.id != null) ids.push(node.id);\n }\n return ids;\n },\n setSelection: (ids) => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const want = new Set(ids);\n api.forEachNode((node) => {\n if (node.id != null) node.setSelected(want.has(node.id));\n });\n },\n selectRange: (fromId, toId) => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const ordered: string[] = [];\n api.forEachNodeAfterFilterAndSort((node) => {\n if (node.id != null) ordered.push(node.id);\n });\n const a = ordered.indexOf(fromId);\n const b = ordered.indexOf(toId);\n if (a < 0 || b < 0) return;\n const [lo, hi] = a <= b ? [a, b] : [b, a];\n const want = new Set(ordered.slice(lo, hi + 1));\n api.forEachNode((node) => {\n if (node.id != null) node.setSelected(want.has(node.id));\n });\n },\n clearSelection: () => {\n agGridRef.current?.api?.deselectAll();\n },\n getFilter: () => agGridRef.current?.api?.getFilterModel() ?? {},\n setFilter: (model) => {\n agGridRef.current?.api?.setFilterModel(model);\n },\n getSort: () => {\n const api = agGridRef.current?.api;\n if (!api) return [];\n return api\n .getColumnState()\n .filter((c) => c.sort === 'asc' || c.sort === 'desc')\n .map((c) => ({ colId: c.colId, sort: c.sort as 'asc' | 'desc' }));\n },\n setSort: (model) => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const next = api.getColumnState().map((c) => {\n const target = model.find((m) => m.colId === c.colId);\n return { ...c, sort: target ? target.sort : null };\n });\n api.applyColumnState({ state: next, defaultState: { sort: null } });\n },\n getCurrentPage: () =>\n agGridRef.current?.api?.paginationGetCurrentPage() ?? 0,\n goToPage: (page) => {\n agGridRef.current?.api?.paginationGoToPage(page);\n },\n getRawApi: () => agGridRef.current?.api,\n }),\n [],\n );\n\n useImperativeHandle(ref, () => handle, [handle]);\n // Agent adapter is keyed on the row-agnostic DataTableHandle; cast here\n // because TData isn't observable from the agent surface.\n useAgentRegistration(dataTableAgent, handle as DataTableHandle, gridId);\n\n const isRtl = i18n.dir() === 'rtl';\n const isLoading = rowData === undefined;\n\n // Reactive — re-renders when the OS preference or theme toggles mid-session.\n const prefersReducedMotion = usePrefersReducedMotion();\n const { resolvedTheme } = useTheme();\n // Suppress compact density in accessible theme — 32px rows violate min-target-size.\n const isAccessible =\n resolvedTheme === 'light-accessible' || resolvedTheme === 'dark-accessible';\n const effectiveDensity =\n isAccessible && density === 'compact' ? 'default' : density;\n\n // Map logical 'single' | 'multiple' → AG Grid v35 object form\n const rowSelectionOption = useMemo(() => {\n if (!rowSelection) return undefined;\n if (rowSelection === 'single') return { mode: 'singleRow' as const };\n return {\n mode: 'multiRow' as const,\n headerCheckbox: true,\n checkboxes: true,\n };\n }, [rowSelection]);\n\n // Column persistence — restore on mount\n const handleGridReady = useCallback(() => {\n if (!gridId || !agGridRef.current?.api) return;\n const saved = loadColumnState(gridId);\n if (saved) {\n agGridRef.current.api.applyColumnState({\n state: saved,\n applyOrder: true,\n });\n }\n }, [gridId]);\n\n const handleColumnStateChange = useCallback(() => {\n if (gridId && agGridRef.current?.api) {\n saveColumnState(gridId, agGridRef.current.api);\n }\n }, [gridId]);\n\n const handleSelectionChanged = useCallback(() => {\n const api = agGridRef.current?.api;\n if (!api) return;\n const rows = api.getSelectedRows();\n setSelectionCount(rows.length);\n onSelectionChanged?.(rows);\n }, [onSelectionChanged]);\n\n const handleSortChanged = useCallback(\n (event: SortChangedEvent<TData>) => {\n const api = agGridRef.current?.api;\n if (api) {\n const colState = api.getColumnState();\n const sortedCol = colState.find((c) => c.sort);\n if (sortedCol) {\n const colId = sortedCol.colId;\n // Use the live AG Grid API so grouped headers and runtime column\n // mutations (visibility toggles, dynamic re-order) resolve correctly.\n const colDef = api.getColumnDef(colId);\n const colName = (colDef?.headerName as string) ?? colId;\n const dirKey =\n sortedCol.sort === 'asc'\n ? 'dataTable.sortAscending'\n : 'dataTable.sortDescending';\n setSortAnnouncement(\n t('dataTable.sortAnnounce', {\n column: colName,\n direction: t(dirKey),\n }),\n );\n } else {\n setSortAnnouncement('');\n }\n }\n onSortChanged?.(event);\n },\n [onSortChanged, t],\n );\n\n const handleFilterChanged = useCallback(\n (event: FilterChangedEvent<TData>) => {\n onFilterChanged?.(event);\n },\n [onFilterChanged],\n );\n\n // Clear sort announcement after screen readers have had time to read it\n useEffect(() => {\n if (!sortAnnouncement) return;\n const id = setTimeout(() => setSortAnnouncement(''), 3000);\n return () => clearTimeout(id);\n }, [sortAnnouncement]);\n\n const NoRowsComponent = noRowsOverlay ?? DefaultNoRowsOverlay;\n const LoadingComponent = loadingOverlay ?? DefaultLoadingOverlay;\n\n const getApi = useCallback(\n () => agGridRef.current?.api as GridApi | undefined,\n [],\n );\n\n const handlePrint = useCallback(() => {\n if (typeof window !== 'undefined') {\n window.print();\n }\n }, []);\n\n const wrapperClass = dataTableVariants({\n density: effectiveDensity,\n bordered,\n className,\n });\n\n // Toolbar composition — render either the consumer-provided children,\n // or a default ExportMenu (CSV + Excel + PDF) so every grid ships with\n // the full export trio for free. Excel + PDF are dynamic-imported by\n // their item handlers so they don't add weight to the main bundle.\n const toolbarContent = children ?? (\n <Toolbar>\n <Toolbar.Actions>\n <Toolbar.ExportMenu />\n </Toolbar.Actions>\n </Toolbar>\n );\n\n // Pagination is auto-disabled in print mode so every row prints.\n const paginationEnabled = printMode ? false : pagination;\n\n return (\n <div\n className=\"ds:flex ds:w-full ds:flex-col ds:gap-[var(--spacing-sm)]\"\n aria-busy={isLoading ? 'true' : undefined}\n data-component=\"data-table\"\n data-component-id={gridId}\n data-print-mode={printMode ? 'true' : undefined}\n >\n {!printMode && (\n <ToolbarProvider\n getApi={getApi}\n selectionCount={selectionCount}\n onPrint={handlePrint}\n >\n {toolbarContent}\n </ToolbarProvider>\n )}\n\n {/* Grid */}\n <div\n className={[wrapperClass, printMode ? '' : heightClass]\n .join(' ')\n .trim()}\n >\n <AgGridReact<TData>\n ref={agGridRef}\n // Opt into v32 CSS-file theming so the `.ag-theme-alfadocs` bridge\n // (src/tokens/ag-grid-theme.css) wins. Without this, AG Grid v33+\n // defaults to the JS Theming API (themeQuartz) which overrides our\n // tokens at runtime — including --ag-font-family.\n theme=\"legacy\"\n columnDefs={columnDefs}\n rowData={rowData}\n /* §11a — every column gets sort + filter + resize + floating\n filter by default. Consumers opt-out per column via\n `sortable: false` / `filter: false`. The spread at the end\n lets `gridOptions.defaultColDef` override individual keys\n without losing the rest.\n\n Note: the column-menu button (`menuTabs` /\n `suppressHeaderMenuButton`) requires `ColumnMenuModule`,\n which is Enterprise in v33+. The floating-filter row is the\n Community-friendly equivalent and covers the primary use\n case — sort + filter without an extra popup. */\n defaultColDef={{\n sortable: true,\n // Default filter = DS-styled text filter so untyped columns\n // (no explicit `filter:` override) inherit the kit's form\n // language instead of AG Grid's stock browser-skinned input.\n // Number / date / select columns opt into their dedicated\n // wrapper per-column.\n filter: TextFilter,\n floatingFilterComponent: TextFloatingFilter,\n resizable: true,\n floatingFilter: true,\n // §13d — faint sort icon advertises which columns are\n // sortable. v33+ moved this from grid-level to defaultColDef.\n unSortIcon: true,\n ...(gridOptions as GridOptions<TData> | undefined)?.defaultColDef,\n }}\n rowSelection={rowSelectionOption}\n pagination={paginationEnabled}\n paginationPageSize={paginationPageSize}\n paginationPageSizeSelector={paginationPageSizeSelector}\n /* §13k — locale-aware pagination chrome (\"1 a 25 di 1.287\" in\n Italian). AG Grid's default renders raw integers. */\n paginationNumberFormatter={(params) =>\n new Intl.NumberFormat(i18n.language).format(params.value)\n }\n animateRows={!prefersReducedMotion}\n enableRtl={isRtl}\n ensureDomOrder\n /* Enable CellSpanModule globally — gate prop required for any\n colDef using `spanRows: true` (Community). Zero runtime cost\n when no column opts in. */\n enableCellSpan\n /* §13a — selecting cell text with the mouse should just work\n (copy a patient ID, an invoice number). AG Grid defaults this\n to false; that breaks user expectation on web tables. */\n enableCellTextSelection\n /* §13b — when a user copies a range, include column headers in\n the clipboard so a paste into Excel/Sheets keeps context. */\n copyHeadersToClipboard\n /* §13c — locale-aware sort (Intl.Collator). \"à\" sorts next to\n \"a\", \"ñ\" next to \"n\". Italian-first matters. */\n accentedSort\n /* §13d unSortIcon — moved to defaultColDef above per v33+\n deprecation. */\n /* §13e — Ctrl/⌘ for multi-column sort. Accounting + clinical\n staff who live in these grids appreciate this. */\n multiSortKey=\"ctrl\"\n /* §13f — dragging a column header outside the grid no longer\n hides the column. Surprising default, easy to trigger by\n accident, hard to recover from without ColumnToggle. */\n suppressDragLeaveHidesColumns\n /* §13g — when row selection is enabled, require explicit\n checkbox/modifier-key selection. Don't fight the primary\n row action (open / edit / navigate) with click-anywhere\n selection. No-op when rowSelection is unset. */\n suppressRowClickSelection={rowSelection ? true : undefined}\n /* §13h — tooltip ergonomics: 500 ms show matches OS, 5 s hide\n gives time to read long content, hover keeps it visible. */\n tooltipShowDelay={500}\n tooltipHideDelay={5000}\n tooltipInteraction\n /* §13i — commit-on-blur contract for inline editing. No-op\n until any column declares `editable: true`. */\n stopEditingWhenCellsLoseFocus\n /* §13j — preserve user column reorder across columnDefs\n prop changes; pairs with the localStorage persistence below. */\n maintainColumnOrder\n /* §13l — Ctrl/⌘+Z for inline edits. No-op until editable\n columns appear. */\n undoRedoCellEditing\n undoRedoCellEditingLimit={20}\n suppressCellFocus={false}\n rowBuffer={10}\n localeText={localeText}\n noRowsOverlayComponent={NoRowsComponent}\n loadingOverlayComponent={LoadingComponent}\n getRowClass={getRowClass}\n pinnedBottomRowData={pinnedBottomRowData}\n domLayout={printMode ? 'autoHeight' : undefined}\n onGridReady={handleGridReady}\n onColumnMoved={handleColumnStateChange}\n onColumnResized={handleColumnStateChange}\n onColumnPinned={handleColumnStateChange}\n onSortChanged={handleSortChanged}\n onFilterChanged={handleFilterChanged}\n onSelectionChanged={handleSelectionChanged}\n {...(gridOptions as GridOptions<TData>)}\n />\n </div>\n\n {/* Footer */}\n {!printMode && (\n <div className=\"ds:flex ds:items-center ds:justify-between type-body-sm ds:text-[color:var(--muted-foreground)]\">\n {selectionCount > 0 ? (\n <span>{t('dataTable.selected', { count: selectionCount })}</span>\n ) : (\n <span />\n )}\n </div>\n )}\n\n {/* Aria-live region for sort announcements */}\n <span role=\"status\" aria-live=\"polite\" className=\"ds:sr-only\">\n {sortAnnouncement}\n </span>\n </div>\n );\n}\n\nconst DataTableBase = forwardRef(DataTableInner) as <TData = unknown>(\n props: DataTableProps<TData> & { ref?: React.Ref<DataTableHandle<TData>> },\n) => React.ReactElement;\n\n(DataTableBase as { displayName?: string }).displayName = 'DataTable';\n\nexport const DataTable = Object.assign(DataTableBase, {\n Toolbar,\n});\n","import { useMemo } from 'react';\n\n/**\n * Compute a pinned total row from a dataset and a list of numeric fields.\n *\n * The returned object is structurally a `TData` with non-summed fields left\n * `undefined` — plug it into `pinnedBottomRowData={[totalRow]}`. Cell renderers\n * in the non-summed columns receive `undefined`, so they should render nothing\n * (all of the DS cell renderers short-circuit on `null`/`undefined`).\n *\n * Pass an optional `labelField` + `labelValue` to show a static caption such\n * as \"Total\" in the first column of the pinned row.\n */\nexport function useTotalRow<TData>(\n rowData: TData[] | undefined,\n sumFields: Array<keyof TData & string>,\n options?: {\n labelField?: keyof TData & string;\n labelValue?: string;\n },\n): TData {\n return useMemo(() => {\n const row: Record<string, unknown> = {};\n\n for (const field of sumFields) {\n let total = 0;\n for (const r of rowData ?? []) {\n const raw = (r as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n if (Number.isFinite(n)) total += n;\n }\n row[field] = total;\n }\n\n if (options?.labelField && options.labelValue !== undefined) {\n row[options.labelField] = options.labelValue;\n }\n\n return row as TData;\n }, [rowData, sumFields, options?.labelField, options?.labelValue]);\n}\n","import { useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { DateRangePicker } from '../../date-range-picker';\nimport type { DateRangeValue } from '../../date-range-picker';\n\n/**\n * Custom AG Grid filter component for date *ranges*. AG Grid Community's\n * built-in `agDateColumnFilter` only handles single-date comparison —\n * platform needs \"between X and Y\" for invoice / transaction lists.\n *\n * Wire on a colDef:\n * ```tsx\n * { field: 'date', filter: DateRangeFilter }\n * ```\n *\n * The filter model has shape `{ type: 'inRange', dateFrom, dateTo }` to\n * stay close to AG Grid's own date-filter convention so server-side\n * adapters can interpret it the same way.\n */\nexport interface DateRangeFilterModel {\n type: 'inRange';\n dateFrom: string | null;\n dateTo: string | null;\n}\n\nfunction toIsoDate(d: Date | undefined): string | null {\n if (!d) return null;\n return d.toISOString().slice(0, 10);\n}\n\nfunction fromIsoDate(s: string | null | undefined): Date | undefined {\n if (!s) return undefined;\n const d = new Date(s);\n return Number.isNaN(d.getTime()) ? undefined : d;\n}\n\nexport function DateRangeFilter(props: CustomFilterProps) {\n const { model, onModelChange, getValue, doesRowPassOtherFilter } = props;\n const initial: DateRangeValue = {\n from: fromIsoDate((model as DateRangeFilterModel | null)?.dateFrom),\n to: fromIsoDate((model as DateRangeFilterModel | null)?.dateTo),\n };\n const [range, setRange] = useState<DateRangeValue>(initial);\n\n // Tell AG Grid how to evaluate a row against the current model. AG Grid\n // calls this for each row; we read the cell value via `getValue(node)`\n // (a Date or ISO string), compare to the bounds.\n useGridFilter({\n doesFilterPass: (params) => {\n const cellValue = getValue(params.node) as\n | Date\n | string\n | null\n | undefined;\n if (!cellValue) return false;\n const cellDate =\n cellValue instanceof Date ? cellValue : fromIsoDate(String(cellValue));\n if (!cellDate) return false;\n if (range.from && cellDate < range.from) return false;\n if (range.to && cellDate > range.to) return false;\n // Respect other filters via the supplied callback if AG Grid uses\n // it (some grid setups call `doesRowPassOtherFilter` before us).\n void doesRowPassOtherFilter;\n return true;\n },\n });\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div className=\"ds:p-[var(--spacing-sm)] ds:min-w-[280px]\">\n <DateRangePicker value={range} onChange={apply} size=\"sm\" />\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `DateRangeFilter`.\n *\n * Renders the kit's `<DateRangePicker>` directly as the floating-filter\n * input — its built-in trigger button + calendar popover IS the filter\n * UI. Earlier versions wrapped the picker in a second `<Popover>`,\n * producing the \"click → empty popover with another trigger → click\n * again → calendar\" double-step that read as duplicated UI.\n */\nexport function DateRangeFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n DateRangeFilterModel\n >,\n) {\n const { model, onModelChange } = props;\n const [range, setRange] = useState<DateRangeValue>({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n });\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div data-component=\"date-range-floating-filter\" className=\"ds:w-full\">\n <DateRangePicker value={range} onChange={apply} size=\"sm\" />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Checkbox } from '../../checkbox';\nimport { Button } from '../../button';\nimport { MultiSelect } from '../../multi-select';\n\n/**\n * Custom AG Grid filter component — multi-select facet filter.\n *\n * The Community-friendly equivalent of AG Grid Enterprise's\n * `agSetColumnFilter`. Surfaces a checkbox list of every value the column\n * can take, so users tick to include / untick to exclude. Much faster than\n * the default `agTextColumnFilter` for closed enums (status, room,\n * operator).\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'status',\n * filter: SelectFilter,\n * filterParams: {\n * options: [\n * { value: 'open', label: 'Aperte' },\n * { value: 'paid', label: 'Pagate' },\n * ],\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'set', values: Array<string | number> }` matches\n * AG Grid Enterprise's set-filter convention so server-side adapters can\n * read either implementation the same way.\n */\n\nexport interface SelectFilterOption {\n value: string | number;\n label: string;\n}\n\nexport interface SelectFilterModel {\n type: 'set';\n values: Array<string | number>;\n}\n\nexport interface SelectFilterParams {\n options?: SelectFilterOption[];\n placeholder?: string;\n}\n\ntype SelectFilterValue = string | number;\n\nfunction toValueKey(v: SelectFilterValue): string {\n return typeof v === 'number' ? `n:${v}` : `s:${v}`;\n}\n\nexport function SelectFilter(\n props: CustomFilterProps<unknown, unknown, SelectFilterModel> &\n SelectFilterParams,\n) {\n const { model, onModelChange, getValue, api, column, options, placeholder } =\n props;\n const { t } = useTranslation('ui');\n\n // Universe of choices. Prefer the explicit `options` filterParam; fall\n // back to the column's distinct rendered values so the filter is useful\n // even when the consumer doesn't enumerate them. The fallback path runs\n // when `options` is omitted and the filter has access to the grid api\n // — `api.forEachNode` is a synchronous read so this is cheap per\n // mount. Consumers wanting a live-updating list should pass `options`.\n const derivedOptions = useMemo<SelectFilterOption[]>(() => {\n if (options && options.length > 0) return options;\n if (!api || !column) return [];\n const seen = new Map<string, SelectFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = getValue(node) as unknown;\n if (raw === null || raw === undefined) return;\n const value =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n if (!seen.has(key)) {\n seen.set(key, { value, label: String(value) });\n }\n });\n return Array.from(seen.values()).sort((a, b) =>\n String(a.label).localeCompare(String(b.label)),\n );\n }, [options, api, column, getValue]);\n\n // Working set — checkboxes mutate `pending` only; we commit to the\n // grid via `onModelChange` when the user clicks Apply (or clears).\n const initialSelected = useMemo<Set<string>>(() => {\n const set = new Set<string>();\n const incoming = model?.values ?? [];\n for (const v of incoming) set.add(toValueKey(v));\n return set;\n }, [model]);\n\n const [pending, setPending] = useState<Set<string>>(initialSelected);\n\n // Sync local `pending` if the model changes externally (e.g. when AG\n // Grid pushes a reset). `model` is the dependency — Set instances are\n // compared by reference in React, so the memo above is sufficient.\n useEffect(() => {\n setPending(initialSelected);\n }, [initialSelected]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const active = model?.values;\n if (!active || active.length === 0) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value: SelectFilterValue =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n return active.some((v) => toValueKey(v) === key);\n },\n });\n\n function toggle(optionKey: string) {\n setPending((prev) => {\n const next = new Set(prev);\n if (next.has(optionKey)) next.delete(optionKey);\n else next.add(optionKey);\n return next;\n });\n }\n\n function apply() {\n if (pending.size === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const opt of derivedOptions) {\n if (pending.has(toValueKey(opt.value))) values.push(opt.value);\n }\n onModelChange({ type: 'set', values });\n }\n\n function clear() {\n setPending(new Set());\n onModelChange(null);\n }\n\n const placeholderLabel = placeholder ?? t('dataTable.selectFilter.all');\n\n return (\n <div\n data-component=\"select-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[200px] ds:max-w-[260px]\"\n >\n <div\n role=\"group\"\n aria-label={placeholderLabel}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:max-h-[240px] ds:overflow-y-auto\"\n >\n {derivedOptions.length === 0 ? (\n <p className=\"ds:text-[length:var(--font-size-sm)] ds:text-[var(--muted-foreground)] ds:py-[var(--spacing-xs)]\">\n {t('dataTable.agGrid.noRowsToShow')}\n </p>\n ) : (\n derivedOptions.map((option) => {\n const key = toValueKey(option.value);\n return (\n <Checkbox\n key={key}\n size=\"sm\"\n label={option.label}\n checked={pending.has(key)}\n onCheckedChange={() => toggle(key)}\n />\n );\n })\n )}\n </div>\n <div className=\"ds:flex ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.selectFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.selectFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `SelectFilter`.\n *\n * Renders the kit's `<MultiSelect>` directly as the floating-filter\n * input — its built-in trigger + checkbox dropdown IS the filter UI.\n * Earlier versions wrapped MultiSelect in another `<Popover>`,\n * producing the \"click trigger → empty popover with another trigger →\n * click → checkbox list\" double-step that read as duplicated UI.\n *\n * MultiSelect's options use `string` values; we string-convert the\n * model's `(string | number)[]` for the trigger and parse back on\n * apply. The grid model still tracks the original primitive types so\n * `doesFilterPass` keeps matching numeric columns correctly.\n */\nexport function SelectFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n SelectFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as SelectFilterParams | undefined) ??\n {};\n const availableOptions = filterParams.options ?? [];\n\n // MultiSelect's `value` is `string[]`. SelectFilter's model carries\n // `(string | number)[]` so we string-convert in / out. Build a lookup\n // from the stringified key back to the original primitive so the\n // model retains the consumer's typing.\n const valueByKey = useMemo(() => {\n const map = new Map<string, SelectFilterValue>();\n for (const opt of availableOptions) map.set(String(opt.value), opt.value);\n return map;\n }, [availableOptions]);\n\n const selectOptions = useMemo(\n () =>\n availableOptions.map((opt) => ({\n value: String(opt.value),\n label: opt.label,\n })),\n [availableOptions],\n );\n\n const currentValue = useMemo(\n () => (model?.values ?? []).map((v) => String(v)),\n [model],\n );\n\n function handleChange(next: string[]) {\n if (next.length === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const k of next) {\n const original = valueByKey.get(k);\n if (original !== undefined) values.push(original);\n }\n onModelChange({ type: 'set', values });\n }\n\n return (\n <div data-component=\"select-floating-filter\" className=\"ds:w-full\">\n <MultiSelect\n size=\"sm\"\n options={selectOptions}\n value={currentValue}\n onChange={handleChange}\n placeholder={filterParams.placeholder}\n allowClear\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Autocomplete } from '../../autocomplete';\nimport { Button } from '../../button';\nimport type { OptionShape } from '../../_shared/option';\n\n/**\n * Custom AG Grid filter component — single-select typeahead filter.\n *\n * Wraps the kit's existing `<Autocomplete>` so the user types to filter a\n * bounded-but-large set of values (e.g. patient names), picks one\n * suggestion, and the grid filters to rows matching that value exactly.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'patient',\n * filter: TypeaheadFilter,\n * filterParams: {\n * options: PATIENTS.map(p => ({ value: p.name, label: p.name })),\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'equals', value: string }` matches AG Grid's\n * text-filter `equals` convention so server-side adapters can read either\n * implementation the same way.\n */\n\nexport interface TypeaheadFilterOption {\n value: string;\n label: string;\n}\n\nexport interface TypeaheadFilterModel {\n type: 'equals';\n value: string;\n}\n\nexport interface TypeaheadFilterParams {\n options?: TypeaheadFilterOption[];\n loadOptions?: (\n input: string,\n opts: { signal: AbortSignal; locale: string },\n ) => Promise<TypeaheadFilterOption[]>;\n placeholder?: string;\n}\n\nfunction normalise(s: string): string {\n return s.trim().toLocaleLowerCase();\n}\n\nexport function TypeaheadFilter(\n props: CustomFilterProps<unknown, unknown, TypeaheadFilterModel> &\n TypeaheadFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n api,\n column,\n options,\n loadOptions,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n // Universe of choices. Prefer explicit `options`; fall back to the\n // column's distinct values when neither `options` nor `loadOptions` is\n // supplied. Same shape as SelectFilter's derivation so the two filters\n // present a consistent experience when consumers don't enumerate.\n const derivedOptions = useMemo<TypeaheadFilterOption[]>(() => {\n if (options && options.length > 0) return options;\n if (!api || !column) return [];\n const seen = new Map<string, TypeaheadFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = getValue(node) as unknown;\n if (raw === null || raw === undefined) return;\n const value = typeof raw === 'string' ? raw : String(raw);\n if (!seen.has(value)) {\n seen.set(value, { value, label: value });\n }\n });\n return Array.from(seen.values()).sort((a, b) =>\n a.label.localeCompare(b.label),\n );\n }, [options, api, column, getValue]);\n\n // Build the async `loadOptions` adapter that <Autocomplete> consumes.\n // Local-options path filters the snapshot synchronously and wraps it\n // in Promise.resolve(); explicit `loadOptions` is passed through.\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? derivedOptions.filter((o) => normalise(o.label).includes(q))\n : derivedOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, derivedOptions]);\n\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const target = model?.value;\n if (!target) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value = typeof raw === 'string' ? raw : String(raw);\n return normalise(value) === normalise(target);\n },\n });\n\n function handleSelect(option: OptionShape) {\n // Autocomplete itself commits `option.label` to the input value; we\n // mirror that here so the displayed text matches what the user just\n // picked, even when label and value diverge (e.g. id vs name).\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n // Clear the applied model when the user empties the input so the\n // grid stops filtering as soon as the field is blank.\n if (next === '' && model) onModelChange(null);\n }\n\n function clear() {\n setDraft('');\n onModelChange(null);\n }\n\n const placeholderLabel =\n placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n return (\n <div\n data-component=\"typeahead-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n <div className=\"ds:flex ds:items-center ds:justify-end ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.typeaheadFilter.clear')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `TypeaheadFilter`.\n *\n * Renders the kit's `<Autocomplete>` directly as the floating-filter\n * input — its built-in text input + portaled dropdown IS the filter\n * UI. Earlier versions wrapped Autocomplete in a second `<Popover>`,\n * producing the \"click trigger → popover with another search input →\n * type → list appears\" double-step that read as duplicated UI.\n */\nexport function TypeaheadFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n TypeaheadFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as\n | TypeaheadFilterParams\n | undefined) ?? {};\n const availableOptions = filterParams.options ?? [];\n const loadOptions = filterParams.loadOptions;\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? availableOptions.filter((o) => normalise(o.label).includes(q))\n : availableOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, availableOptions]);\n\n // Track the input's display value separately from the applied model.\n // The user can type freely; we only apply when they pick an option\n // from the dropdown (committing a known value to the model). Clearing\n // the input clears the filter.\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n function handleSelect(option: OptionShape) {\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n if (next === '' && model) onModelChange(null);\n }\n\n return (\n <div data-component=\"typeahead-floating-filter\" className=\"ds:w-full\">\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { NumberInput } from '../../number-input';\nimport { Select } from '../../select';\nimport { Button } from '../../button';\n\n/**\n * Custom AG Grid filter component for numeric columns. AG Grid Community's\n * built-in `agNumberColumnFilter` paints a stock browser-skinned\n * `<input type=\"number\">` that does not match the kit's form language —\n * this wraps the DS `<NumberInput>` + `<Select>` so totals, prices,\n * quantities, etc. line up visually with neighbouring DS-styled cells.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'total',\n * filter: NumberFilter,\n * floatingFilterComponent: NumberFloatingFilter,\n * filterParams: { defaultOperator: 'greaterThan', min: 0 },\n * }\n * ```\n *\n * The full-popover variant exposes the operator dropdown (equals,\n * greaterThan, inRange, blank, …); the floating-filter row is a single\n * compact input whose operator is fixed to `defaultOperator`. Both speak\n * the same `NumberFilterModel` so server-side adapters can read either.\n *\n * Model shape `{ type, filter, filterTo? }` matches AG Grid's own\n * `agNumberColumnFilter` vocabulary so adapters can interchange.\n */\n\nexport type NumberFilterOperator =\n | 'equals'\n | 'notEqual'\n | 'greaterThan'\n | 'greaterThanOrEqual'\n | 'lessThan'\n | 'lessThanOrEqual'\n | 'inRange'\n | 'blank'\n | 'notBlank';\n\nexport interface NumberFilterModel {\n type: NumberFilterOperator;\n filter: number;\n filterTo?: number;\n}\n\nexport interface NumberFilterParams {\n defaultOperator?: NumberFilterOperator;\n min?: number;\n max?: number;\n step?: number;\n placeholder?: string;\n}\n\nconst ALL_OPERATORS: NumberFilterOperator[] = [\n 'equals',\n 'notEqual',\n 'greaterThan',\n 'greaterThanOrEqual',\n 'lessThan',\n 'lessThanOrEqual',\n 'inRange',\n 'blank',\n 'notBlank',\n];\n\nfunction operatorTakesValue(op: NumberFilterOperator): boolean {\n return op !== 'blank' && op !== 'notBlank';\n}\n\nfunction operatorTakesRange(op: NumberFilterOperator): boolean {\n return op === 'inRange';\n}\n\nfunction evaluate(\n op: NumberFilterOperator,\n cell: number | null,\n primary: number | null,\n secondary: number | null,\n): boolean {\n if (op === 'blank') return cell === null;\n if (op === 'notBlank') return cell !== null;\n if (cell === null) return false;\n if (primary === null) return true;\n switch (op) {\n case 'equals':\n return cell === primary;\n case 'notEqual':\n return cell !== primary;\n case 'greaterThan':\n return cell > primary;\n case 'greaterThanOrEqual':\n return cell >= primary;\n case 'lessThan':\n return cell < primary;\n case 'lessThanOrEqual':\n return cell <= primary;\n case 'inRange': {\n if (secondary === null) return cell >= primary;\n const lo = Math.min(primary, secondary);\n const hi = Math.max(primary, secondary);\n return cell >= lo && cell <= hi;\n }\n default:\n return true;\n }\n}\n\nfunction coerceCell(raw: unknown): number | null {\n if (raw === null || raw === undefined || raw === '') return null;\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isNaN(n) ? null : n;\n}\n\nexport function NumberFilter(\n props: CustomFilterProps<unknown, unknown, NumberFilterModel> &\n NumberFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n defaultOperator,\n min,\n max,\n step,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n const initialOperator: NumberFilterOperator =\n model?.type ?? defaultOperator ?? 'equals';\n const [operator, setOperator] =\n useState<NumberFilterOperator>(initialOperator);\n const [primary, setPrimary] = useState<number | null>(model?.filter ?? null);\n const [secondary, setSecondary] = useState<number | null>(\n model?.filterTo ?? null,\n );\n\n // If AG Grid pushes an externally-cleared / reset model, mirror it in\n // local state so the UI stays consistent with the applied filter.\n useEffect(() => {\n if (model === null) {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n return;\n }\n setOperator(model.type);\n setPrimary(model.filter ?? null);\n setSecondary(model.filterTo ?? null);\n }, [model, defaultOperator]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n if (!model) return true;\n const cell = coerceCell(getValue(params.node));\n return evaluate(\n model.type,\n cell,\n model.filter ?? null,\n model.filterTo ?? null,\n );\n },\n });\n\n const operatorOptions = useMemo(\n () =>\n ALL_OPERATORS.map((op) => ({\n value: op,\n label: t(`dataTable.numberFilter.operators.${op}`),\n })),\n [t],\n );\n\n const placeholderLabel =\n placeholder ?? t('dataTable.numberFilter.placeholder');\n\n function apply() {\n if (!operatorTakesValue(operator)) {\n onModelChange({ type: operator, filter: 0 });\n return;\n }\n if (primary === null) {\n onModelChange(null);\n return;\n }\n if (operatorTakesRange(operator)) {\n onModelChange({\n type: operator,\n filter: primary,\n filterTo: secondary ?? undefined,\n });\n return;\n }\n onModelChange({ type: operator, filter: primary });\n }\n\n function clear() {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n onModelChange(null);\n }\n\n const showValue = operatorTakesValue(operator);\n const showRange = operatorTakesRange(operator);\n\n return (\n <div\n data-component=\"number-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Select\n size=\"sm\"\n options={operatorOptions}\n value={operator}\n onValueChange={(next) => {\n if (next === '') return;\n setOperator(next as NumberFilterOperator);\n }}\n aria-label={t('dataTable.numberFilter.operators.equals')}\n />\n {showValue && !showRange && (\n <NumberInput\n size=\"sm\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n )}\n {showRange && (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <NumberInput\n size=\"sm\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.from')}\n aria-label={t('dataTable.numberFilter.from')}\n />\n <NumberInput\n size=\"sm\"\n value={secondary}\n onChange={setSecondary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.to')}\n aria-label={t('dataTable.numberFilter.to')}\n />\n </div>\n )}\n <div className=\"ds:flex ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.numberFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.numberFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `NumberFilter`.\n *\n * Renders the kit's `<NumberInput>` directly as the inline filter input\n * with a fixed operator (`defaultOperator`, or `'equals'`). The operator\n * dropdown lives only in the full popover — the floating-filter row is\n * deliberately compact, matching the way `agNumberColumnFilter` ships\n * with AG Grid Community.\n *\n * Debounced commit at 200 ms so each keystroke does not re-run the grid\n * filter. Empty input or invalid number commits `null` so the column\n * reverts to \"no filter\" rather than `filter: NaN`.\n */\nexport function NumberFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n NumberFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as NumberFilterParams | undefined) ??\n {};\n const operator: NumberFilterOperator =\n filterParams.defaultOperator ?? 'equals';\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.numberFilter.placeholder');\n\n const [draft, setDraft] = useState<number | null>(model?.filter ?? null);\n\n // Sync local draft when the model is reset externally (e.g. a global\n // clear from the column-header menu's \"Clear\" button).\n useEffect(() => {\n setDraft(model?.filter ?? null);\n }, [model?.filter]);\n\n // Debounced commit. We don't pull a hook in for this — a single\n // useEffect + setTimeout is cheaper than the cost of importing one,\n // and AG Grid only re-renders this floating filter per keystroke.\n useEffect(() => {\n if (draft === (model?.filter ?? null)) return;\n const handle = setTimeout(() => {\n if (draft === null || Number.isNaN(draft)) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: operator, filter: draft });\n }, 200);\n return () => clearTimeout(handle);\n // `model` intentionally excluded — we only want to react to user\n // edits of `draft`. Model resets sync via the effect above.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [draft, operator]);\n\n return (\n <div data-component=\"number-floating-filter\" className=\"ds:w-full\">\n <NumberInput\n size=\"sm\"\n value={draft}\n onChange={setDraft}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n </div>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Badge } from '../../badge/badge';\n\nexport type BadgeVariant = 'neutral' | 'info' | 'success' | 'warning' | 'error';\n\nexport interface StatusCellRendererParams {\n variantMap?: Record<string, BadgeVariant>;\n}\n\nexport function StatusCellRenderer(\n props: CustomCellRendererProps & StatusCellRendererParams,\n) {\n const { value, variantMap } = props;\n const variant: BadgeVariant = variantMap?.[value as string] ?? 'neutral';\n return (\n <Badge variant={variant} withDot size=\"sm\">\n {String(value ?? '')}\n </Badge>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface UserCellValue {\n name: string;\n src?: string;\n}\n\nexport function UserCellRenderer(\n props: CustomCellRendererProps<unknown, UserCellValue>,\n) {\n const { value } = props;\n if (!value) return null;\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Avatar name={value.name} src={value.src} size=\"sm\" />\n <span>{value.name}</span>\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface ImageCellRendererParams {\n /** Field name on the row whose value holds the image URL. */\n srcField: string;\n /** Optional field name holding alt text. Falls back to '' (decorative). */\n altField?: string;\n /**\n * Optional field name holding a name string. When the src URL is missing or\n * rejected, the cell falls back to `<Avatar name={fallback}>` so the cell\n * still has a visual.\n */\n fallbackField?: string;\n /** Visual size of the image. Matches `<Avatar>` sizes (sm=32, md=40, lg=48). */\n size?: 'sm' | 'md' | 'lg';\n /** Corner radius preset. `circle` matches `<Avatar>`. */\n shape?: 'square' | 'rounded' | 'circle';\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ImageCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-8',\n md: 'ds:size-10',\n lg: 'ds:size-12',\n};\n\nconst SHAPE_CLASS: Record<\n NonNullable<ImageCellRendererParams['shape']>,\n string\n> = {\n square: 'ds:rounded-none',\n rounded: 'ds:rounded-[var(--radius-md)]',\n circle: 'ds:rounded-[var(--radius-full)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Only accept http(s) and data: URLs. Reject `javascript:` / `vbscript:` /\n// any other smuggled scheme. Browsers won't execute non-image data: URLs in\n// `<img>`, but rejecting them in JS gives a single audit point.\nconst SAFE_SRC_RE = /^(?:https?:|data:image\\/)/i;\n\nfunction sanitizeSrc(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const trimmed = raw.trim();\n if (trimmed.length === 0) return undefined;\n return SAFE_SRC_RE.test(trimmed) ? trimmed : undefined;\n}\n\nexport function ImageCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ImageCellRendererParams,\n) {\n const {\n data,\n srcField,\n altField,\n fallbackField,\n size = 'md',\n shape = 'rounded',\n } = props;\n\n if (!data) return null;\n\n const rawSrc = readField(data, srcField);\n const src = sanitizeSrc(rawSrc);\n const alt = altField ? (readField(data, altField) ?? '') : '';\n const fallbackName = fallbackField\n ? readField(data, fallbackField)\n : undefined;\n\n if (!src) {\n if (fallbackName) {\n return <Avatar name={fallbackName} size={size} />;\n }\n return null;\n }\n\n return (\n <img\n src={src}\n alt={alt}\n loading=\"lazy\"\n decoding=\"async\"\n className={['ds:object-cover', SIZE_CLASS[size], SHAPE_CLASS[shape]].join(\n ' ',\n )}\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport { Tag } from '../../tag/tag';\nimport { Tooltip } from '../../tooltip';\n\nexport interface TagListCellRendererParams {\n maxVisible?: number;\n}\n\nexport function TagListCellRenderer(\n props: CustomCellRendererProps<unknown, string[]> & TagListCellRendererParams,\n) {\n const { value, maxVisible = 3 } = props;\n const { t } = useTranslation();\n\n if (!Array.isArray(value) || value.length === 0) return null;\n\n const visible = value.slice(0, maxVisible);\n const overflow = value.length - maxVisible;\n\n return (\n <span className=\"ds:inline-flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n {visible.map((tag) => (\n <Tag key={tag} label={tag} size=\"sm\" />\n ))}\n {overflow > 0 && (\n <Tooltip label={value.slice(maxVisible).join(', ')}>\n <Tag\n label={t('inputs.multiSelect.overflow', { count: overflow })}\n size=\"sm\"\n variant=\"neutral\"\n fill=\"outline\"\n />\n </Tooltip>\n )}\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Timestamp } from '../../timestamp';\n\nexport type DateCellFormat = 'date' | 'time' | 'datetime' | 'relative';\n\nexport interface DateCellRendererParams {\n /** Which preset to use. Default `'date'`. */\n format?: DateCellFormat;\n /** Escape hatch — overrides the preset entirely. */\n options?: Intl.DateTimeFormatOptions;\n}\n\nconst PRESETS: Record<\n Exclude<DateCellFormat, 'relative'>,\n Intl.DateTimeFormatOptions\n> = {\n date: { year: 'numeric', month: 'short', day: 'numeric' },\n time: { hour: '2-digit', minute: '2-digit' },\n datetime: {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n },\n};\n\nexport function DateCellRenderer(\n props: CustomCellRendererProps & DateCellRendererParams,\n) {\n const { value, format = 'date', options } = props;\n if (value == null || value === '') return null;\n\n // `shape=\"bare\"` keeps the cell font inherited from --ag-font-size. Timestamp\n // still emits a proper `<time dateTime>` for assistive tech and feeds.\n if (format === 'relative' && !options) {\n return <Timestamp value={value as string | Date} shape=\"bare\" />;\n }\n\n return (\n <Timestamp\n value={value as string | Date}\n format=\"absolute\"\n shape=\"bare\"\n absoluteFormat={\n options ?? PRESETS[format === 'relative' ? 'date' : format]\n }\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface CurrencyCellRendererParams {\n /** ISO 4217 currency code. Default `'EUR'`. */\n currency?: string;\n /** Apply a destructive color token to negative amounts. */\n colorNegative?: boolean;\n /** Render the value with strikethrough — used for written-off balances. */\n strikethrough?: boolean;\n /** `Intl.NumberFormat` escape hatch. Merged on top of currency defaults. */\n options?: Intl.NumberFormatOptions;\n}\n\nfunction toNumber(value: unknown): number | null {\n if (value == null || value === '') return null;\n const n = typeof value === 'number' ? value : Number(value);\n return Number.isFinite(n) ? n : null;\n}\n\nexport function CurrencyCellRenderer(\n props: CustomCellRendererProps & CurrencyCellRendererParams,\n) {\n const {\n value,\n currency = 'EUR',\n colorNegative,\n strikethrough,\n options,\n } = props;\n const { i18n } = useTranslation();\n const n = toNumber(value);\n if (n === null) return null;\n\n const locale = i18n.language || 'en';\n const formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n ...options,\n }).format(n);\n\n const classNames = ['ds:tabular-nums'];\n if (colorNegative && n < 0)\n classNames.push('ds:text-[color:var(--destructive)]');\n if (strikethrough) classNames.push('line-through');\n\n return <span className={classNames.join(' ')}>{formatted}</span>;\n}\n","import { cloneElement, isValidElement, type ReactNode } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { IconButton } from '../../button/icon-button';\n\n// Lucide icons render at their intrinsic 24×24 unless given a `size` prop or\n// `size-*` class. The IconButton's wrapping span is only `size-4` (16px), so a\n// bare `<Trash2 />` overflows and, inside AG Grid's `overflow: hidden` cells,\n// gets clipped into horizontal slivers. Coerce icon nodes to the expected size.\nfunction sizeIcon(node: ReactNode): ReactNode {\n if (!isValidElement(node)) return node;\n const element = node as React.ReactElement<{\n className?: string;\n size?: number;\n }>;\n const existingClass = element.props.className ?? '';\n const className = /\\bsize-|\\bw-|\\bh-/.test(existingClass)\n ? existingClass\n : `${existingClass} size-4`.trim();\n return cloneElement(element, { className, size: element.props.size ?? 16 });\n}\n\nexport interface ActionDef<TData = unknown> {\n /** Lucide-style icon node. */\n icon: ReactNode;\n /** Accessible label — also used as the tooltip. */\n label: string;\n /** Invoked with the row data. */\n onClick: (data: TData) => void;\n /** Disable the action. Pass a predicate for per-row disablement. */\n disabled?: boolean | ((data: TData) => boolean);\n /** Human-readable reason shown in the tooltip when disabled. */\n disabledReason?: string;\n /** `destructive` swaps the button intent. */\n variant?: 'default' | 'destructive';\n /** Hide the action entirely. Pass a predicate for per-row hiding. */\n hidden?: boolean | ((data: TData) => boolean);\n}\n\nexport interface ActionsCellRendererParams<TData = unknown> {\n actions: ActionDef<TData>[];\n}\n\nfunction resolve<T>(\n flag: boolean | ((data: T) => boolean) | undefined,\n data: T,\n): boolean {\n if (typeof flag === 'function') return flag(data);\n return Boolean(flag);\n}\n\nexport function ActionsCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ActionsCellRendererParams<TData>,\n) {\n const { data, actions } = props;\n if (!data) return null;\n\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {actions.map((action, index) => {\n if (resolve(action.hidden, data)) return null;\n const isDisabled = resolve(action.disabled, data);\n const tooltip =\n isDisabled && action.disabledReason\n ? action.disabledReason\n : action.label;\n\n const isDestructive = action.variant === 'destructive';\n\n return (\n <IconButton\n // Action defs are referentially stable from consumers; index is\n // acceptable here because actions do not reorder within a row.\n\n key={index}\n size=\"sm\"\n intent=\"ghost\"\n icon={sizeIcon(action.icon)}\n tooltip={tooltip}\n aria-label={action.label}\n disabled={isDisabled}\n onClick={(event) => {\n event.stopPropagation();\n action.onClick(data);\n }}\n className={\n isDestructive\n ? 'ds:text-[color:var(--destructive)] ds:hover:text-[color:var(--destructive-hover)]'\n : undefined\n }\n />\n );\n })}\n </span>\n );\n}\n","import type { MouseEvent } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\n\ntype Getter<T, TData> = T | ((data: TData) => T | undefined);\n\nexport interface LinkCellRendererParams<TData = unknown> {\n /** Anchor href — or a function that derives it from the row. */\n href?: Getter<string, TData>;\n /** Fallback / additional onClick. Prevents default when provided without href. */\n onClick?: (data: TData) => void;\n /** Small text rendered below the link — supports a row-aware function. */\n secondary?: Getter<string, TData>;\n}\n\nfunction resolve<T, TData>(\n source: Getter<T, TData> | undefined,\n data: TData,\n): T | undefined {\n if (typeof source === 'function') {\n return (source as (data: TData) => T | undefined)(data);\n }\n return source;\n}\n\nfunction safeHref(href: string): string {\n return /^(https?:\\/\\/|\\/|#|mailto:|tel:)/i.test(href) ? href : '#';\n}\n\nexport function LinkCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & LinkCellRendererParams<TData>,\n) {\n const { value, data, href, onClick, secondary } = props;\n if (!data) return null;\n\n const resolvedHref = resolve(href, data);\n const resolvedSecondary = resolve(secondary, data);\n const content = value == null || value === '' ? '' : String(value);\n\n const linkClasses = [\n 'ds:text-[color:var(--primary)]',\n 'ds:hover:underline',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:rounded-[var(--radius-sm)]',\n ].join(' ');\n\n const handleClick = (event: MouseEvent) => {\n if (!onClick) return;\n if (!resolvedHref) event.preventDefault();\n event.stopPropagation();\n onClick(data);\n };\n\n return (\n <span className=\"ds:flex ds:flex-col ds:leading-tight\">\n {resolvedHref ? (\n <a\n href={safeHref(resolvedHref)}\n onClick={handleClick}\n className={linkClasses}\n >\n {content}\n </a>\n ) : (\n <button\n type=\"button\"\n onClick={handleClick}\n className={[\n 'ds:appearance-none ds:bg-transparent ds:p-0 ds:text-start',\n linkClasses,\n ].join(' ')}\n >\n {content}\n </button>\n )}\n {resolvedSecondary ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {resolvedSecondary}\n </span>\n ) : null}\n </span>\n );\n}\n","import { useState, type ReactNode } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { CheckSquare, Square } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface ToggleCellRendererParams<TData = unknown> {\n /**\n * Fires with the row and the new target value. May return a `Promise` —\n * if it rejects, the consumer is expected to revert the underlying value\n * and flash the row with `data-table-row-error` (return that row class\n * from `getRowClass`). Use `onError` below to be notified inside this\n * renderer.\n */\n onToggle: (data: TData, newValue: boolean) => void | Promise<void>;\n /**\n * Optional reject hook. Fires when the `onToggle` promise rejects, with\n * the row and the error. The button auto-disables during the in-flight\n * promise and re-enables on either settle.\n */\n onError?: (data: TData, error: unknown) => void;\n /** Icon shown when the current value is truthy. */\n trueIcon?: ReactNode;\n /** Icon shown when the current value is falsy. */\n falseIcon?: ReactNode;\n /** Extra classes applied to the \"on\" icon — defaults to success token. */\n trueClass?: string;\n /** Extra classes applied to the \"off\" icon. */\n falseClass?: string;\n /** Accessible label. Falls back to the default on/off announcements. */\n label?: string;\n}\n\nexport function ToggleCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData, boolean> &\n ToggleCellRendererParams<TData>,\n) {\n const {\n value,\n data,\n onToggle,\n onError,\n trueIcon,\n falseIcon,\n trueClass = 'ds:text-[color:var(--success)]',\n falseClass = 'ds:text-[color:var(--muted-foreground)]',\n label,\n } = props;\n const { t } = useTranslation();\n const [pending, setPending] = useState(false);\n if (!data) return null;\n\n const isOn = Boolean(value);\n const icon = isOn\n ? (trueIcon ?? <CheckSquare aria-hidden className=\"ds:size-4\" />)\n : (falseIcon ?? <Square aria-hidden className=\"ds:size-4\" />);\n const stateClass = isOn ? trueClass : falseClass;\n const resolvedLabel =\n label ?? (isOn ? t('inputs.switch.on') : t('inputs.switch.off'));\n\n async function handleClick(event: React.MouseEvent) {\n event.stopPropagation();\n if (pending || !data) return;\n const next = !isOn;\n const result = onToggle(data, next);\n if (result && typeof (result as Promise<void>).then === 'function') {\n setPending(true);\n try {\n await result;\n } catch (err) {\n onError?.(data, err);\n } finally {\n setPending(false);\n }\n }\n }\n\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={isOn}\n aria-busy={pending}\n aria-label={resolvedLabel}\n disabled={pending}\n onClick={handleClick}\n className={[\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)] ds:min-w-[var(--min-target-size)]',\n 'ds:appearance-none ds:bg-transparent ds:p-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:disabled:opacity-50',\n stateClass,\n ].join(' ')}\n >\n {icon}\n </button>\n );\n}\n","import { useRef } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useIsomorphicLayoutEffect } from '../../../hooks/use-isomorphic-layout-effect';\n\nexport interface ColorDotCellRendererParams {\n /** Field name on the row whose value holds the hex color. */\n colorField: string;\n /** Visual size of the dot. */\n size?: 'sm' | 'md' | 'lg';\n /** Optional label shown next to the dot. */\n labelField?: string;\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ColorDotCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-[var(--icon-size-sm)]',\n md: 'ds:size-[var(--icon-size-md)]',\n lg: 'ds:size-[var(--icon-size-lg)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Only accept trusted CSS color forms. Anything outside this allow-list\n// (including smuggled `url()` or extra declarations) is dropped so the\n// CSS custom-property writer can't be used to inject styles.\nconst HEX_RE = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;\nconst RGB_RE = /^rgba?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst HSL_RE = /^hsla?\\(\\s*[\\d.\\s,%/]+\\)$/i;\nconst CSS_VAR_RE = /^var\\(--[a-z0-9-]+(?:,\\s*[^)]+)?\\)$/i;\n\nfunction sanitizeColor(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const v = raw.trim();\n if (\n HEX_RE.test(v) ||\n RGB_RE.test(v) ||\n HSL_RE.test(v) ||\n CSS_VAR_RE.test(v)\n ) {\n return v;\n }\n return undefined;\n}\n\nexport function ColorDotCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ColorDotCellRendererParams,\n) {\n const { data, colorField, size = 'md', labelField } = props;\n const dotRef = useRef<HTMLSpanElement | null>(null);\n const rawColor = data ? readField(data, colorField) : undefined;\n const color = sanitizeColor(rawColor);\n const label = data && labelField ? readField(data, labelField) : undefined;\n\n // Apply the dynamic color via a CSS custom property on the element.\n // Keeps hex/rgb literals out of JSX (constraint #2 and #4). The data\n // itself drives the color — constraints only forbid hardcoded colors\n // in component source, not in consumer row data.\n useIsomorphicLayoutEffect(() => {\n const el = dotRef.current;\n if (!el) return;\n if (color) {\n el.style.setProperty('--data-table-dot-color', color);\n } else {\n el.style.removeProperty('--data-table-dot-color');\n }\n }, [color]);\n\n if (!color) return null;\n\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span\n ref={dotRef}\n aria-hidden=\"true\"\n className={[\n 'ds:inline-block ds:shrink-0 ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--data-table-dot-color)]',\n 'ds:border ds:border-[color:var(--border)]',\n SIZE_CLASS[size],\n ].join(' ')}\n />\n {label ? <span>{label}</span> : null}\n </span>\n );\n}\n","import type { ColDef } from 'ag-grid-community';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\n\nexport interface BalanceLine {\n /** User-visible label for this line. */\n label: string;\n /** Field name on the row whose numeric value is rendered. */\n valueField: string;\n /** `'currency'` renders via Intl, `'percent'` appends `%`, `'number'` raw. Default `'number'`. */\n format?: 'currency' | 'percent' | 'number';\n}\n\nexport interface BalanceCellRendererParams {\n lines: BalanceLine[];\n /** ISO 4217 code, used by `currency`-formatted lines. Default `'EUR'`. */\n currency?: string;\n /** Apply destructive color to negative values. */\n highlightNegative?: boolean;\n}\n\nfunction readNumber(row: unknown, field: string): number | null {\n if (!row || typeof row !== 'object') return null;\n const raw = (row as Record<string, unknown>)[field];\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isFinite(n) ? n : null;\n}\n\n/**\n * Renders a compact set of label / value pairs inside a single AG Grid cell.\n *\n * Layout is **horizontal** with middle-dot separators so the cell fits\n * inside the default AG Grid row height without spilling into the row\n * below. Use the SALDI / Listini patterns (Totale · Incassato · Da Incassare)\n * as the canonical example.\n *\n * If a consumer's content wraps (long localized labels, narrow columns)\n * they can opt into row auto-growth by spreading\n * {@link balanceCellRendererColDefDefaults} onto the column definition.\n */\nexport function BalanceCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & BalanceCellRendererParams,\n) {\n const { data, lines, currency = 'EUR', highlightNegative } = props;\n const { i18n } = useTranslation();\n if (!data) return null;\n\n const locale = i18n.language || 'en';\n\n const formatLine = (\n line: BalanceLine,\n ): { label: string; formatted: string; negative: boolean } | null => {\n const n = readNumber(data, line.valueField);\n if (n === null) return null;\n\n let formatted: string;\n switch (line.format ?? 'number') {\n case 'currency':\n formatted = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n }).format(n);\n break;\n case 'percent':\n formatted = new Intl.NumberFormat(locale, {\n style: 'percent',\n maximumFractionDigits: 1,\n }).format(n / 100);\n break;\n default:\n formatted = new Intl.NumberFormat(locale).format(n);\n }\n\n return {\n label: line.label,\n formatted,\n negative: Boolean(highlightNegative) && n < 0,\n };\n };\n\n const rendered = lines\n .map(formatLine)\n .filter(\n (x): x is { label: string; formatted: string; negative: boolean } =>\n x !== null,\n );\n if (rendered.length === 0) return null;\n\n return (\n <div\n className={[\n 'ds:flex',\n 'ds:flex-wrap',\n 'ds:items-center',\n 'ds:gap-x-[var(--spacing-sm)]',\n 'ds:gap-y-0',\n 'type-meta',\n 'ds:leading-tight',\n ].join(' ')}\n >\n {rendered.map((item, idx) => (\n <span\n key={`${item.label}-${idx}`}\n className=\"ds:inline-flex ds:items-baseline ds:gap-x-[var(--spacing-xs)]\"\n >\n {idx > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:me-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\"\n >\n ·\n </span>\n ) : null}\n <span className=\"ds:text-[color:var(--muted-foreground)]\">\n {item.label}\n </span>\n <span\n className={[\n 'ds:tabular-nums',\n 'ds:font-medium',\n item.negative ? 'ds:text-[color:var(--destructive)]' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {item.formatted}\n </span>\n </span>\n ))}\n </div>\n );\n}\n\n/**\n * Column-definition defaults consumers can spread onto a `ColDef` when they\n * want the renderer's wrapped / multi-line behaviour to grow the row.\n *\n * The default compact horizontal layout is engineered to fit the standard\n * AG Grid row height, so this opt-in is only needed when a long label set\n * wraps across two or more lines and the consumer would rather grow the\n * row than wrap silently.\n *\n * AG Grid does NOT auto-grow row height to fit a tall cell unless\n * `autoHeight` and `wrapText` are set on the colDef itself — a cell\n * renderer can't impose that from inside.\n *\n * @example\n * ```ts\n * {\n * headerName: 'Saldi',\n * cellRenderer: BalanceCellRenderer,\n * cellRendererParams: { lines, currency: 'EUR' },\n * ...balanceCellRendererColDefDefaults,\n * }\n * ```\n */\nexport const balanceCellRendererColDefDefaults: Readonly<\n Pick<ColDef, 'autoHeight' | 'wrapText'>\n> = {\n autoHeight: true,\n wrapText: true,\n};\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\n/**\n * Inline text editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The cell renderer (default\n * or custom) takes over again once editing stops.\n *\n * AG Grid commits on Enter or Tab or blur; cancels on Escape. The consumer\n * receives the committed value via `onCellValueChanged`.\n */\nexport function EditableTextCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, string>,\n) {\n const { initialValue, onValueChange, stopEditing, column } = props;\n const [value, setValue] = useState<string>(initialValue ?? '');\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Focus + select on mount so typing replaces the current value.\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n // The current value is pushed to AG Grid via `onValueChange` on every\n // keystroke — AG Grid commits the most recent value when editing stops.\n // No `useGridCellEditor` hook needed for that contract.\n\n // Thread the column header into the input's accessible name so screen\n // readers announce \"Edit text, {column}\" instead of an unlabelled input.\n // AG Grid doesn't auto-wire the column header to cell editors.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setValue(next);\n onValueChange(next);\n }}\n onKeyDown={(e) => {\n // Escape cancels, Enter/Tab commit — AG Grid handles both, but we\n // explicitly stop editing on Enter so the consumer sees the commit\n // immediately rather than waiting for the next focus blur.\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none',\n // Input surface chrome: rounded border + bg + focus halo.\n INPUT_SURFACE_CHROME,\n // Use the `md` height (`--min-target-size`) so the input\n // auto-lifts to 48px under `.theme-accessible` to satisfy\n // WCAG 2.5.5 target size.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { CustomCellEditorProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport {\n INPUT_SURFACE_CHROME,\n INPUT_SURFACE_HEIGHT,\n INPUT_SURFACE_PADDING_X,\n INPUT_SURFACE_TEXT,\n} from '../../_shared/input-surface';\n\nexport interface EditableCurrencyCellEditorParams {\n /** ISO 4217 currency code (e.g. `EUR`, `USD`). Defaults to `EUR`. */\n currency?: string;\n /** Decimal places allowed in the editor. Defaults to 2 (cents precision). */\n decimals?: number;\n /** Minimum allowed value — values below this are clamped on commit. */\n min?: number;\n /** Maximum allowed value — values above this are clamped on commit. */\n max?: number;\n}\n\n/**\n * Inline numeric editor that visually matches `<TextInput size=\"sm\">`. Use as\n * `cellEditor` on a colDef with `editable: true`. The display formatting is\n * still the renderer's job — once editing stops, the cell hands back to\n * `CurrencyCellRenderer` (or whichever renderer the colDef declares).\n *\n * Stores a Number, not a string, so consumers receive `row.amount = 12.5`\n * not `\"12.5\"`. Strips locale separators on each change so commas/dots in\n * any language convert to a clean numeric value.\n */\nexport function EditableCurrencyCellRenderer<TData = unknown>(\n props: CustomCellEditorProps<TData, number> &\n EditableCurrencyCellEditorParams,\n) {\n const {\n initialValue,\n onValueChange,\n stopEditing,\n column,\n decimals = 2,\n min,\n max,\n } = props;\n const { i18n } = useTranslation();\n const inputRef = useRef<HTMLInputElement | null>(null);\n // Thread the column header into the input's accessible name — see\n // editable-text-cell-renderer.tsx for the rationale.\n const headerName =\n (column?.getColDef?.()?.headerName as string | undefined) ?? undefined;\n\n // Local string state so the user can type intermediate values like \"12.\"\n // before the trailing zero arrives. We commit a Number to AG Grid on each\n // change for consumers that watch row state live; the final commit fires\n // when editing stops.\n const [draft, setDraft] = useState<string>(() => {\n if (initialValue == null || Number.isNaN(initialValue)) return '';\n return String(initialValue);\n });\n\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n el.select();\n }, []);\n\n function parseDraft(input: string): number | null {\n if (input.trim().length === 0) return null;\n // Accept either the user's locale decimal separator or a `.`. Strip\n // grouping characters (locale thousands separators, plus spaces).\n const lang = i18n.language || 'en';\n const partsFmt = new Intl.NumberFormat(lang).formatToParts(12345.6);\n const groupChar = partsFmt.find((p) => p.type === 'group')?.value ?? '';\n const decimalChar =\n partsFmt.find((p) => p.type === 'decimal')?.value ?? '.';\n const cleaned = input\n .replace(new RegExp(`\\\\${groupChar}`, 'g'), '')\n .replace(decimalChar, '.')\n .replace(/[^\\d.-]/g, '');\n const n = Number(cleaned);\n return Number.isFinite(n) ? n : null;\n }\n\n function commit(input: string) {\n const parsed = parseDraft(input);\n if (parsed == null) {\n onValueChange(null);\n return;\n }\n // Clamp first, then round to the declared precision so we never\n // persist floating-point dust from string parsing.\n let clamped = parsed;\n if (typeof min === 'number') clamped = Math.max(min, clamped);\n if (typeof max === 'number') clamped = Math.min(max, clamped);\n const factor = 10 ** decimals;\n onValueChange(Math.round(clamped * factor) / factor);\n }\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n // Inputmode hints mobile keyboards to show the decimal pad instead\n // of the full keyboard. type=\"number\" would also work but spinners\n // and locale parsing are inconsistent across browsers.\n inputMode=\"decimal\"\n value={draft}\n aria-label={headerName}\n onChange={(e) => {\n const next = e.target.value;\n setDraft(next);\n commit(next);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n stopEditing();\n }\n // Escape — AG Grid cancels by default; the editor doesn't need\n // explicit handling beyond what AG Grid wires automatically.\n }}\n className={[\n 'ds:block ds:w-full ds:appearance-none ds:text-end ds:tabular-nums',\n INPUT_SURFACE_CHROME,\n // Use `md` height — see editable-text-cell-renderer for rationale.\n INPUT_SURFACE_HEIGHT.md,\n INPUT_SURFACE_TEXT.sm,\n INPUT_SURFACE_PADDING_X.sm,\n ].join(' ')}\n />\n );\n}\n"],"names":["__iconNode","Columns2","createLucideIcon","sizeIcon","node","isValidElement","element","existingClass","className","cloneElement","ToolbarContext","createContext","useToolbarContext","caller","ctx","useContext","ToolbarProvider","getApi","selectionCount","onPrint","children","value","useMemo","jsx","TOOLBAR_BASE","ToolbarRoot","forwardRef","props","ref","FilterBar","Actions","ExportCsv","label","onExport","intent","rest","t","useTranslation","handleClick","useCallback","api","IconButton","Download","resolveTokenToRgb","varName","fallback","probe","computed","match","defaultExportPdf","options","jsPDF","autoTable","n","visibleColumns","col","head","body","cells","headerFill","headerText","bodyText","alternateFill","doc","ExportPdf","onClick","fileName","FileText","Print","Printer","QuickSearch","placeholder","debounceMs","setValue","useState","timerRef","useRef","useEffect","TextInput","e","Search","Refresh","onRefresh","RefreshCw","describeFilterModel","model","m","type","filterTo","FilterChips","chips","setChips","quickFilter","setQuickFilter","refresh","cols","next","colId","c","headerName","qf","handler","_event","clearOne","clearAll","jsxs","Tag","Button","X","FacetFilter","field","active","setActive","apply","opt","isActive","DEFAULT_EXPORT_ITEMS","defaultExportXlsx","ExcelJS","workbook","sheet","headerRow","hex","r","g","b","cell","buffer","blob","url","link","ExportMenuContext","useExportMenuContext","ExportMenu","itemsContent","f","ExportMenuItem","DropdownMenu","defaultLabel","format","defaultIcon","FileSpreadsheet","readColumnEntries","ColumnToggle","open","setOpen","columns","setColumns","draggingColId","setDraggingColId","dragOverColId","setDragOverColId","toggleColumn","nextVisible","prev","moveColumn","fromColId","toColId","fromIdx","toIdx","moved","labelText","Popover","Columns","isDragging","isDragOver","GripVertical","Checkbox","checked","BulkAction","icon","variant","size","ExportMenuNamespace","Toolbar","OPERATORS","makeMatcher","locale","collator","indexOf","haystack","needle","i","a","coerceToString","raw","TextFilter","onModelChange","getValue","defaultOperator","initialOperator","operator","setOperator","draft","setDraft","matcher","i18next","useGridFilter","params","clear","operatorOptions","op","placeholderLabel","Select","event","TextFloatingFilter","column","filterParams","_b","_a","timer","clearImmediate","dataTableAgent","handle","args","ModuleRegistry","AllCommunityModule","dataTableVariants","cva","useAgLocaleText","DefaultLoadingOverlay","_","Skeleton","DefaultNoRowsOverlay","EmptyState","loadColumnState","gridId","saveColumnState","DataTableInner","columnDefs","rowData","rowSelection","pagination","paginationPageSize","paginationPageSizeSelector","onSelectionChanged","onSortChanged","onFilterChanged","noRowsOverlay","loadingOverlay","gridOptions","density","bordered","heightClass","getRowClass","pinnedBottomRowData","printMode","i18n","agGridRef","setSelectionCount","sortAnnouncement","setSortAnnouncement","localeText","ids","want","fromId","toId","ordered","lo","hi","target","page","useImperativeHandle","useAgentRegistration","isRtl","isLoading","prefersReducedMotion","usePrefersReducedMotion","resolvedTheme","useTheme","effectiveDensity","rowSelectionOption","handleGridReady","saved","handleColumnStateChange","handleSelectionChanged","rows","handleSortChanged","sortedCol","colDef","colName","dirKey","handleFilterChanged","id","NoRowsComponent","LoadingComponent","handlePrint","wrapperClass","toolbarContent","paginationEnabled","AgGridReact","DataTableBase","DataTable","useTotalRow","sumFields","row","total","toIsoDate","d","fromIsoDate","s","DateRangeFilter","doesRowPassOtherFilter","initial","range","setRange","cellValue","cellDate","DateRangePicker","DateRangeFloatingFilter","toValueKey","v","SelectFilter","derivedOptions","seen","key","initialSelected","set","incoming","pending","setPending","toggle","optionKey","values","option","SelectFloatingFilter","availableOptions","valueByKey","map","selectOptions","currentValue","handleChange","k","original","MultiSelect","normalise","TypeaheadFilter","loadOptions","adapterLoadOptions","query","opts","o","q","handleSelect","Autocomplete","TypeaheadFloatingFilter","ALL_OPERATORS","operatorTakesValue","operatorTakesRange","evaluate","primary","secondary","coerceCell","NumberFilter","min","max","step","setPrimary","setSecondary","showValue","showRange","NumberInput","NumberFloatingFilter","StatusCellRenderer","variantMap","Badge","UserCellRenderer","Avatar","SIZE_CLASS","SHAPE_CLASS","readField","SAFE_SRC_RE","sanitizeSrc","trimmed","ImageCellRenderer","data","srcField","altField","fallbackField","shape","rawSrc","src","alt","fallbackName","TagListCellRenderer","maxVisible","visible","overflow","tag","Tooltip","PRESETS","DateCellRenderer","Timestamp","toNumber","CurrencyCellRenderer","currency","colorNegative","strikethrough","formatted","classNames","resolve","flag","ActionsCellRenderer","actions","action","index","isDisabled","tooltip","isDestructive","source","safeHref","href","LinkCellRenderer","resolvedHref","resolvedSecondary","content","linkClasses","ToggleCellRenderer","onToggle","onError","trueIcon","falseIcon","trueClass","falseClass","isOn","CheckSquare","Square","stateClass","resolvedLabel","result","err","HEX_RE","RGB_RE","HSL_RE","CSS_VAR_RE","sanitizeColor","ColorDotCellRenderer","colorField","labelField","dotRef","rawColor","color","useIsomorphicLayoutEffect","el","readNumber","BalanceCellRenderer","lines","highlightNegative","formatLine","line","rendered","x","item","idx","EditableTextCellRenderer","initialValue","onValueChange","stopEditing","inputRef","INPUT_SURFACE_CHROME","INPUT_SURFACE_HEIGHT","INPUT_SURFACE_TEXT","INPUT_SURFACE_PADDING_X","EditableCurrencyCellRenderer","decimals","parseDraft","input","lang","partsFmt","groupChar","p","decimalChar","cleaned","commit","parsed","clamped","factor"],"mappings":"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","x_google_ignoreList":[0]}