@multiplatform.one/table 7.34.3 → 7.35.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 (396) hide show
  1. package/dist/cjs/components/ChildTable/index.cjs +26 -23
  2. package/dist/cjs/components/ChildTable/index.native.js +26 -23
  3. package/dist/cjs/components/ChildTable/index.native.js.map +1 -1
  4. package/dist/cjs/components/DataTable/DataTableCardControls.cjs +3 -8
  5. package/dist/cjs/components/DataTable/DataTableCardControls.native.js +3 -8
  6. package/dist/cjs/components/DataTable/DataTableCardControls.native.js.map +1 -1
  7. package/dist/cjs/components/DataTable/DataTableContext.cjs +1 -2
  8. package/dist/cjs/components/DataTable/DataTableContext.native.js +1 -2
  9. package/dist/cjs/components/DataTable/DataTableContext.native.js.map +1 -1
  10. package/dist/cjs/components/DataTable/DataTableDocumentList.cjs +84 -46
  11. package/dist/cjs/components/DataTable/DataTableDocumentList.native.js +102 -57
  12. package/dist/cjs/components/DataTable/DataTableDocumentList.native.js.map +1 -1
  13. package/dist/cjs/components/DataTable/DataTableInfiniteTail.cjs +1 -1
  14. package/dist/cjs/components/DataTable/DataTableInfiniteTail.native.js +1 -1
  15. package/dist/cjs/components/DataTable/DataTableInfiniteTail.native.js.map +1 -1
  16. package/dist/cjs/components/DataTable/DataTableMobileCards.cjs +5 -11
  17. package/dist/cjs/components/DataTable/DataTableMobileCards.native.js +5 -11
  18. package/dist/cjs/components/DataTable/DataTableMobileCards.native.js.map +1 -1
  19. package/dist/cjs/components/DataTable/DataTableRoot.cjs +601 -606
  20. package/dist/cjs/components/DataTable/DataTableRoot.native.js +705 -710
  21. package/dist/cjs/components/DataTable/DataTableRoot.native.js.map +1 -1
  22. package/dist/cjs/components/DataTable/DataTableVirtualized.cjs +3 -2
  23. package/dist/cjs/components/DataTable/DataTableVirtualized.native.js +3 -2
  24. package/dist/cjs/components/DataTable/DataTableVirtualized.native.js.map +1 -1
  25. package/dist/cjs/components/DataTable/documentListSlots.cjs +8 -1
  26. package/dist/cjs/components/DataTable/documentListSlots.native.js +8 -1
  27. package/dist/cjs/components/DataTable/documentListSlots.native.js.map +1 -1
  28. package/dist/cjs/components/DataTable/index.native.js +264 -252
  29. package/dist/cjs/components/DataTable/index.native.js.map +1 -1
  30. package/dist/cjs/components/DataTableCell/index.cjs +2 -5
  31. package/dist/cjs/components/DataTableCell/index.native.js +2 -5
  32. package/dist/cjs/components/DataTableCell/index.native.js.map +1 -1
  33. package/dist/cjs/components/DataTableColumnPinning/index.cjs +2 -1
  34. package/dist/cjs/components/DataTableColumnPinning/index.native.js +2 -1
  35. package/dist/cjs/components/DataTableColumnPinning/index.native.js.map +1 -1
  36. package/dist/cjs/components/DataTableFilterButton/index.cjs +3 -5
  37. package/dist/cjs/components/DataTableFilterButton/index.native.js +3 -5
  38. package/dist/cjs/components/DataTableFilterButton/index.native.js.map +1 -1
  39. package/dist/cjs/components/DataTableFilterChips/index.cjs +0 -1
  40. package/dist/cjs/components/DataTableFilterChips/index.native.js +0 -1
  41. package/dist/cjs/components/DataTableFilters/index.cjs +11 -19
  42. package/dist/cjs/components/DataTableFilters/index.native.js +11 -19
  43. package/dist/cjs/components/DataTableFilters/index.native.js.map +1 -1
  44. package/dist/cjs/components/DataTableGrouping/index.cjs +5 -5
  45. package/dist/cjs/components/DataTableGrouping/index.native.js +7 -7
  46. package/dist/cjs/components/DataTableGrouping/index.native.js.map +1 -1
  47. package/dist/cjs/components/DataTablePagination/index.cjs +14 -18
  48. package/dist/cjs/components/DataTablePagination/index.native.js +14 -18
  49. package/dist/cjs/components/DataTablePagination/index.native.js.map +1 -1
  50. package/dist/cjs/components/DataTableSearch/index.cjs +5 -7
  51. package/dist/cjs/components/DataTableSearch/index.native.js +5 -7
  52. package/dist/cjs/components/DataTableSearch/index.native.js.map +1 -1
  53. package/dist/cjs/components/DataTableToolbar/index.cjs +2 -10
  54. package/dist/cjs/components/DataTableToolbar/index.native.js +2 -10
  55. package/dist/cjs/components/DataTableToolbar/index.native.js.map +1 -1
  56. package/dist/cjs/components/DataTableViewOptions/index.cjs +5 -3
  57. package/dist/cjs/components/DataTableViewOptions/index.native.js +6 -4
  58. package/dist/cjs/components/DataTableViewOptions/index.native.js.map +1 -1
  59. package/dist/cjs/components/KnobDialog.cjs +4 -34
  60. package/dist/cjs/components/KnobDialog.native.js +3 -34
  61. package/dist/cjs/components/KnobDialog.native.js.map +1 -1
  62. package/dist/cjs/components/SavedFilterDropdown.cjs +0 -1
  63. package/dist/cjs/components/SavedFilterDropdown.native.js +0 -1
  64. package/dist/cjs/components/SavedFilterDropdown.native.js.map +1 -1
  65. package/dist/cjs/components/SimpleTable/ScrollFrame.cjs +51 -0
  66. package/dist/cjs/components/SimpleTable/ScrollFrame.native.js +84 -0
  67. package/dist/cjs/components/SimpleTable/ScrollFrame.native.js.map +1 -0
  68. package/dist/cjs/components/SimpleTable/columnSizing.cjs +50 -0
  69. package/dist/cjs/components/SimpleTable/columnSizing.native.js +71 -0
  70. package/dist/cjs/components/SimpleTable/columnSizing.native.js.map +1 -0
  71. package/dist/cjs/components/SimpleTable/index.cjs +149 -96
  72. package/dist/cjs/components/SimpleTable/index.native.js +163 -109
  73. package/dist/cjs/components/SimpleTable/index.native.js.map +1 -1
  74. package/dist/cjs/components/TableInput/RowDetailEditor.cjs +1 -6
  75. package/dist/cjs/components/TableInput/RowDetailEditor.native.js +1 -5
  76. package/dist/cjs/components/TableInput/RowDetailEditor.native.js.map +1 -1
  77. package/dist/cjs/components/TableInput/index.cjs +4 -19
  78. package/dist/cjs/components/TableInput/index.native.js +2 -11
  79. package/dist/cjs/components/TableInput/index.native.js.map +1 -1
  80. package/dist/esm/components/ChildTable/index.mjs +26 -23
  81. package/dist/esm/components/ChildTable/index.mjs.map +1 -1
  82. package/dist/esm/components/ChildTable/index.native.js +26 -23
  83. package/dist/esm/components/ChildTable/index.native.js.map +1 -1
  84. package/dist/esm/components/DataTable/DataTableCardControls.mjs +3 -8
  85. package/dist/esm/components/DataTable/DataTableCardControls.mjs.map +1 -1
  86. package/dist/esm/components/DataTable/DataTableCardControls.native.js +3 -8
  87. package/dist/esm/components/DataTable/DataTableCardControls.native.js.map +1 -1
  88. package/dist/esm/components/DataTable/DataTableContext.mjs +1 -2
  89. package/dist/esm/components/DataTable/DataTableContext.mjs.map +1 -1
  90. package/dist/esm/components/DataTable/DataTableContext.native.js +1 -2
  91. package/dist/esm/components/DataTable/DataTableContext.native.js.map +1 -1
  92. package/dist/esm/components/DataTable/DataTableDocumentList.mjs +86 -48
  93. package/dist/esm/components/DataTable/DataTableDocumentList.mjs.map +1 -1
  94. package/dist/esm/components/DataTable/DataTableDocumentList.native.js +104 -59
  95. package/dist/esm/components/DataTable/DataTableDocumentList.native.js.map +1 -1
  96. package/dist/esm/components/DataTable/DataTableInfiniteTail.mjs +1 -1
  97. package/dist/esm/components/DataTable/DataTableInfiniteTail.mjs.map +1 -1
  98. package/dist/esm/components/DataTable/DataTableInfiniteTail.native.js +1 -1
  99. package/dist/esm/components/DataTable/DataTableInfiniteTail.native.js.map +1 -1
  100. package/dist/esm/components/DataTable/DataTableMobileCards.mjs +5 -11
  101. package/dist/esm/components/DataTable/DataTableMobileCards.mjs.map +1 -1
  102. package/dist/esm/components/DataTable/DataTableMobileCards.native.js +5 -11
  103. package/dist/esm/components/DataTable/DataTableMobileCards.native.js.map +1 -1
  104. package/dist/esm/components/DataTable/DataTableRoot.mjs +603 -608
  105. package/dist/esm/components/DataTable/DataTableRoot.mjs.map +1 -1
  106. package/dist/esm/components/DataTable/DataTableRoot.native.js +707 -712
  107. package/dist/esm/components/DataTable/DataTableRoot.native.js.map +1 -1
  108. package/dist/esm/components/DataTable/DataTableVirtualized.mjs +4 -3
  109. package/dist/esm/components/DataTable/DataTableVirtualized.mjs.map +1 -1
  110. package/dist/esm/components/DataTable/DataTableVirtualized.native.js +4 -3
  111. package/dist/esm/components/DataTable/DataTableVirtualized.native.js.map +1 -1
  112. package/dist/esm/components/DataTable/documentListSlots.mjs +8 -1
  113. package/dist/esm/components/DataTable/documentListSlots.mjs.map +1 -1
  114. package/dist/esm/components/DataTable/documentListSlots.native.js +8 -1
  115. package/dist/esm/components/DataTable/documentListSlots.native.js.map +1 -1
  116. package/dist/esm/components/DataTable/index.native.js +265 -253
  117. package/dist/esm/components/DataTable/index.native.js.map +1 -1
  118. package/dist/esm/components/DataTableCell/index.mjs +2 -5
  119. package/dist/esm/components/DataTableCell/index.mjs.map +1 -1
  120. package/dist/esm/components/DataTableCell/index.native.js +2 -5
  121. package/dist/esm/components/DataTableCell/index.native.js.map +1 -1
  122. package/dist/esm/components/DataTableColumnPinning/index.mjs +2 -1
  123. package/dist/esm/components/DataTableColumnPinning/index.mjs.map +1 -1
  124. package/dist/esm/components/DataTableColumnPinning/index.native.js +2 -1
  125. package/dist/esm/components/DataTableColumnPinning/index.native.js.map +1 -1
  126. package/dist/esm/components/DataTableFilterButton/index.mjs +4 -6
  127. package/dist/esm/components/DataTableFilterButton/index.mjs.map +1 -1
  128. package/dist/esm/components/DataTableFilterButton/index.native.js +4 -6
  129. package/dist/esm/components/DataTableFilterButton/index.native.js.map +1 -1
  130. package/dist/esm/components/DataTableFilterChips/index.mjs +0 -1
  131. package/dist/esm/components/DataTableFilterChips/index.mjs.map +1 -1
  132. package/dist/esm/components/DataTableFilterChips/index.native.js +0 -1
  133. package/dist/esm/components/DataTableFilters/index.mjs +12 -20
  134. package/dist/esm/components/DataTableFilters/index.mjs.map +1 -1
  135. package/dist/esm/components/DataTableFilters/index.native.js +12 -20
  136. package/dist/esm/components/DataTableFilters/index.native.js.map +1 -1
  137. package/dist/esm/components/DataTableGrouping/index.mjs +6 -6
  138. package/dist/esm/components/DataTableGrouping/index.mjs.map +1 -1
  139. package/dist/esm/components/DataTableGrouping/index.native.js +8 -8
  140. package/dist/esm/components/DataTableGrouping/index.native.js.map +1 -1
  141. package/dist/esm/components/DataTablePagination/index.mjs +15 -19
  142. package/dist/esm/components/DataTablePagination/index.mjs.map +1 -1
  143. package/dist/esm/components/DataTablePagination/index.native.js +15 -19
  144. package/dist/esm/components/DataTablePagination/index.native.js.map +1 -1
  145. package/dist/esm/components/DataTableSearch/index.mjs +5 -7
  146. package/dist/esm/components/DataTableSearch/index.mjs.map +1 -1
  147. package/dist/esm/components/DataTableSearch/index.native.js +5 -7
  148. package/dist/esm/components/DataTableSearch/index.native.js.map +1 -1
  149. package/dist/esm/components/DataTableToolbar/index.mjs +2 -10
  150. package/dist/esm/components/DataTableToolbar/index.mjs.map +1 -1
  151. package/dist/esm/components/DataTableToolbar/index.native.js +2 -10
  152. package/dist/esm/components/DataTableToolbar/index.native.js.map +1 -1
  153. package/dist/esm/components/DataTableViewOptions/index.mjs +6 -4
  154. package/dist/esm/components/DataTableViewOptions/index.mjs.map +1 -1
  155. package/dist/esm/components/DataTableViewOptions/index.native.js +7 -5
  156. package/dist/esm/components/DataTableViewOptions/index.native.js.map +1 -1
  157. package/dist/esm/components/KnobDialog.mjs +6 -36
  158. package/dist/esm/components/KnobDialog.mjs.map +1 -1
  159. package/dist/esm/components/KnobDialog.native.js +5 -36
  160. package/dist/esm/components/KnobDialog.native.js.map +1 -1
  161. package/dist/esm/components/SavedFilterDropdown.mjs +0 -1
  162. package/dist/esm/components/SavedFilterDropdown.mjs.map +1 -1
  163. package/dist/esm/components/SavedFilterDropdown.native.js +0 -1
  164. package/dist/esm/components/SavedFilterDropdown.native.js.map +1 -1
  165. package/dist/esm/components/SimpleTable/ScrollFrame.mjs +25 -0
  166. package/dist/esm/components/SimpleTable/ScrollFrame.mjs.map +1 -0
  167. package/dist/esm/components/SimpleTable/ScrollFrame.native.js +55 -0
  168. package/dist/esm/components/SimpleTable/ScrollFrame.native.js.map +1 -0
  169. package/dist/esm/components/SimpleTable/columnSizing.mjs +25 -0
  170. package/dist/esm/components/SimpleTable/columnSizing.mjs.map +1 -0
  171. package/dist/esm/components/SimpleTable/columnSizing.native.js +43 -0
  172. package/dist/esm/components/SimpleTable/columnSizing.native.js.map +1 -0
  173. package/dist/esm/components/SimpleTable/index.mjs +150 -97
  174. package/dist/esm/components/SimpleTable/index.mjs.map +1 -1
  175. package/dist/esm/components/SimpleTable/index.native.js +164 -110
  176. package/dist/esm/components/SimpleTable/index.native.js.map +1 -1
  177. package/dist/esm/components/TableInput/RowDetailEditor.mjs +1 -6
  178. package/dist/esm/components/TableInput/RowDetailEditor.mjs.map +1 -1
  179. package/dist/esm/components/TableInput/RowDetailEditor.native.js +1 -5
  180. package/dist/esm/components/TableInput/RowDetailEditor.native.js.map +1 -1
  181. package/dist/esm/components/TableInput/index.mjs +5 -20
  182. package/dist/esm/components/TableInput/index.mjs.map +1 -1
  183. package/dist/esm/components/TableInput/index.native.js +3 -12
  184. package/dist/esm/components/TableInput/index.native.js.map +1 -1
  185. package/dist/jsx/components/ChildTable/index.mjs +26 -23
  186. package/dist/jsx/components/ChildTable/index.mjs.map +1 -1
  187. package/dist/jsx/components/ChildTable/index.native.js +26 -23
  188. package/dist/jsx/components/ChildTable/index.native.js.map +1 -1
  189. package/dist/jsx/components/DataTable/DataTableCardControls.mjs +3 -8
  190. package/dist/jsx/components/DataTable/DataTableCardControls.mjs.map +1 -1
  191. package/dist/jsx/components/DataTable/DataTableCardControls.native.js +3 -8
  192. package/dist/jsx/components/DataTable/DataTableCardControls.native.js.map +1 -1
  193. package/dist/jsx/components/DataTable/DataTableContext.mjs +1 -2
  194. package/dist/jsx/components/DataTable/DataTableContext.mjs.map +1 -1
  195. package/dist/jsx/components/DataTable/DataTableContext.native.js +1 -2
  196. package/dist/jsx/components/DataTable/DataTableContext.native.js.map +1 -1
  197. package/dist/jsx/components/DataTable/DataTableDocumentList.mjs +86 -48
  198. package/dist/jsx/components/DataTable/DataTableDocumentList.mjs.map +1 -1
  199. package/dist/jsx/components/DataTable/DataTableDocumentList.native.js +102 -57
  200. package/dist/jsx/components/DataTable/DataTableDocumentList.native.js.map +1 -1
  201. package/dist/jsx/components/DataTable/DataTableInfiniteTail.mjs +1 -1
  202. package/dist/jsx/components/DataTable/DataTableInfiniteTail.mjs.map +1 -1
  203. package/dist/jsx/components/DataTable/DataTableInfiniteTail.native.js +1 -1
  204. package/dist/jsx/components/DataTable/DataTableInfiniteTail.native.js.map +1 -1
  205. package/dist/jsx/components/DataTable/DataTableMobileCards.mjs +5 -11
  206. package/dist/jsx/components/DataTable/DataTableMobileCards.mjs.map +1 -1
  207. package/dist/jsx/components/DataTable/DataTableMobileCards.native.js +5 -11
  208. package/dist/jsx/components/DataTable/DataTableMobileCards.native.js.map +1 -1
  209. package/dist/jsx/components/DataTable/DataTableRoot.mjs +603 -608
  210. package/dist/jsx/components/DataTable/DataTableRoot.mjs.map +1 -1
  211. package/dist/jsx/components/DataTable/DataTableRoot.native.js +705 -710
  212. package/dist/jsx/components/DataTable/DataTableRoot.native.js.map +1 -1
  213. package/dist/jsx/components/DataTable/DataTableVirtualized.mjs +4 -3
  214. package/dist/jsx/components/DataTable/DataTableVirtualized.mjs.map +1 -1
  215. package/dist/jsx/components/DataTable/DataTableVirtualized.native.js +3 -2
  216. package/dist/jsx/components/DataTable/DataTableVirtualized.native.js.map +1 -1
  217. package/dist/jsx/components/DataTable/documentListSlots.mjs +8 -1
  218. package/dist/jsx/components/DataTable/documentListSlots.mjs.map +1 -1
  219. package/dist/jsx/components/DataTable/documentListSlots.native.js +8 -1
  220. package/dist/jsx/components/DataTable/documentListSlots.native.js.map +1 -1
  221. package/dist/jsx/components/DataTable/index.native.js +264 -252
  222. package/dist/jsx/components/DataTable/index.native.js.map +1 -1
  223. package/dist/jsx/components/DataTableCell/index.mjs +2 -5
  224. package/dist/jsx/components/DataTableCell/index.mjs.map +1 -1
  225. package/dist/jsx/components/DataTableCell/index.native.js +2 -5
  226. package/dist/jsx/components/DataTableCell/index.native.js.map +1 -1
  227. package/dist/jsx/components/DataTableColumnPinning/index.mjs +2 -1
  228. package/dist/jsx/components/DataTableColumnPinning/index.mjs.map +1 -1
  229. package/dist/jsx/components/DataTableColumnPinning/index.native.js +2 -1
  230. package/dist/jsx/components/DataTableColumnPinning/index.native.js.map +1 -1
  231. package/dist/jsx/components/DataTableFilterButton/index.mjs +4 -6
  232. package/dist/jsx/components/DataTableFilterButton/index.mjs.map +1 -1
  233. package/dist/jsx/components/DataTableFilterButton/index.native.js +3 -5
  234. package/dist/jsx/components/DataTableFilterButton/index.native.js.map +1 -1
  235. package/dist/jsx/components/DataTableFilterChips/index.mjs +0 -1
  236. package/dist/jsx/components/DataTableFilterChips/index.mjs.map +1 -1
  237. package/dist/jsx/components/DataTableFilterChips/index.native.js +0 -1
  238. package/dist/jsx/components/DataTableFilters/index.mjs +12 -20
  239. package/dist/jsx/components/DataTableFilters/index.mjs.map +1 -1
  240. package/dist/jsx/components/DataTableFilters/index.native.js +11 -19
  241. package/dist/jsx/components/DataTableFilters/index.native.js.map +1 -1
  242. package/dist/jsx/components/DataTableGrouping/index.mjs +6 -6
  243. package/dist/jsx/components/DataTableGrouping/index.mjs.map +1 -1
  244. package/dist/jsx/components/DataTableGrouping/index.native.js +7 -7
  245. package/dist/jsx/components/DataTableGrouping/index.native.js.map +1 -1
  246. package/dist/jsx/components/DataTablePagination/index.mjs +15 -19
  247. package/dist/jsx/components/DataTablePagination/index.mjs.map +1 -1
  248. package/dist/jsx/components/DataTablePagination/index.native.js +14 -18
  249. package/dist/jsx/components/DataTablePagination/index.native.js.map +1 -1
  250. package/dist/jsx/components/DataTableSearch/index.mjs +5 -7
  251. package/dist/jsx/components/DataTableSearch/index.mjs.map +1 -1
  252. package/dist/jsx/components/DataTableSearch/index.native.js +5 -7
  253. package/dist/jsx/components/DataTableSearch/index.native.js.map +1 -1
  254. package/dist/jsx/components/DataTableToolbar/index.mjs +2 -10
  255. package/dist/jsx/components/DataTableToolbar/index.mjs.map +1 -1
  256. package/dist/jsx/components/DataTableToolbar/index.native.js +2 -10
  257. package/dist/jsx/components/DataTableToolbar/index.native.js.map +1 -1
  258. package/dist/jsx/components/DataTableViewOptions/index.mjs +6 -4
  259. package/dist/jsx/components/DataTableViewOptions/index.mjs.map +1 -1
  260. package/dist/jsx/components/DataTableViewOptions/index.native.js +6 -4
  261. package/dist/jsx/components/DataTableViewOptions/index.native.js.map +1 -1
  262. package/dist/jsx/components/KnobDialog.mjs +6 -36
  263. package/dist/jsx/components/KnobDialog.mjs.map +1 -1
  264. package/dist/jsx/components/KnobDialog.native.js +3 -34
  265. package/dist/jsx/components/KnobDialog.native.js.map +1 -1
  266. package/dist/jsx/components/SavedFilterDropdown.mjs +0 -1
  267. package/dist/jsx/components/SavedFilterDropdown.mjs.map +1 -1
  268. package/dist/jsx/components/SavedFilterDropdown.native.js +0 -1
  269. package/dist/jsx/components/SavedFilterDropdown.native.js.map +1 -1
  270. package/dist/jsx/components/SimpleTable/ScrollFrame.mjs +25 -0
  271. package/dist/jsx/components/SimpleTable/ScrollFrame.mjs.map +1 -0
  272. package/dist/jsx/components/SimpleTable/ScrollFrame.native.js +84 -0
  273. package/dist/jsx/components/SimpleTable/ScrollFrame.native.js.map +1 -0
  274. package/dist/jsx/components/SimpleTable/columnSizing.mjs +25 -0
  275. package/dist/jsx/components/SimpleTable/columnSizing.mjs.map +1 -0
  276. package/dist/jsx/components/SimpleTable/columnSizing.native.js +71 -0
  277. package/dist/jsx/components/SimpleTable/columnSizing.native.js.map +1 -0
  278. package/dist/jsx/components/SimpleTable/index.mjs +150 -97
  279. package/dist/jsx/components/SimpleTable/index.mjs.map +1 -1
  280. package/dist/jsx/components/SimpleTable/index.native.js +163 -109
  281. package/dist/jsx/components/SimpleTable/index.native.js.map +1 -1
  282. package/dist/jsx/components/TableInput/RowDetailEditor.mjs +1 -6
  283. package/dist/jsx/components/TableInput/RowDetailEditor.mjs.map +1 -1
  284. package/dist/jsx/components/TableInput/RowDetailEditor.native.js +1 -5
  285. package/dist/jsx/components/TableInput/RowDetailEditor.native.js.map +1 -1
  286. package/dist/jsx/components/TableInput/index.mjs +5 -20
  287. package/dist/jsx/components/TableInput/index.mjs.map +1 -1
  288. package/dist/jsx/components/TableInput/index.native.js +2 -11
  289. package/dist/jsx/components/TableInput/index.native.js.map +1 -1
  290. package/package.json +12 -12
  291. package/src/components/ChildTable/ChildTable.stories.tsx +1 -2
  292. package/src/components/ChildTable/childTable.spec.tsx +2 -2
  293. package/src/components/ChildTable/childTable.zebra.spec.tsx +3 -3
  294. package/src/components/ChildTable/index.tsx +29 -26
  295. package/src/components/DataTable/DataTable.spec.tsx +49 -2
  296. package/src/components/DataTable/DataTable.stories.tsx +5 -5
  297. package/src/components/DataTable/DataTableCardControls.tsx +5 -10
  298. package/src/components/DataTable/DataTableContext.ts +5 -7
  299. package/src/components/DataTable/DataTableDocumentList.tsx +98 -39
  300. package/src/components/DataTable/DataTableInfiniteTail.tsx +1 -1
  301. package/src/components/DataTable/DataTableMobileCards.tsx +4 -9
  302. package/src/components/DataTable/DataTableRoot.tsx +900 -898
  303. package/src/components/DataTable/DataTableVirtualized.tsx +4 -2
  304. package/src/components/DataTable/FieldsInCells.stories.tsx +0 -1
  305. package/src/components/DataTable/compoundComponent.spec.tsx +7 -21
  306. package/src/components/DataTable/dataTableDocumentList.spec.tsx +94 -0
  307. package/src/components/DataTable/dataTableMobileCards.spec.tsx +19 -22
  308. package/src/components/DataTable/documentListSlots.ts +25 -6
  309. package/src/components/DataTable/footerLayout.spec.tsx +7 -7
  310. package/src/components/DataTable/index.native.tsx +329 -322
  311. package/src/components/DataTable/smallTableFooter.spec.tsx +61 -0
  312. package/src/components/DataTableCell/DataTableCell.stories.tsx +0 -2
  313. package/src/components/DataTableCell/index.tsx +3 -7
  314. package/src/components/DataTableColumnPinning/index.tsx +2 -1
  315. package/src/components/DataTableDateFilter/index.tsx +1 -1
  316. package/src/components/DataTableFilterButton/index.tsx +8 -5
  317. package/src/components/DataTableFilterChips/index.tsx +1 -1
  318. package/src/components/DataTableFilters/DataTableFilters.spec.tsx +3 -14
  319. package/src/components/DataTableFilters/DataTableFilters.stories.tsx +1 -6
  320. package/src/components/DataTableFilters/index.tsx +19 -17
  321. package/src/components/DataTableGrouping/index.tsx +9 -8
  322. package/src/components/DataTablePagination/DataTablePagination.spec.tsx +21 -11
  323. package/src/components/DataTablePagination/DataTablePagination.stories.tsx +2 -19
  324. package/src/components/DataTablePagination/DataTablePagination.width.spec.tsx +13 -13
  325. package/src/components/DataTablePagination/index.tsx +19 -15
  326. package/src/components/DataTableSearch/DataTableSearch.stories.tsx +1 -1
  327. package/src/components/DataTableSearch/index.tsx +7 -7
  328. package/src/components/DataTableToolbar/index.tsx +1 -7
  329. package/src/components/DataTableViewOptions/DataTableViewOptions.spec.tsx +5 -5
  330. package/src/components/DataTableViewOptions/DataTableViewOptions.stories.tsx +1 -1
  331. package/src/components/DataTableViewOptions/index.tsx +15 -6
  332. package/src/components/FilterOperatorValueEditor/FilterOperatorValueEditor.spec.tsx +17 -37
  333. package/src/components/KnobDialog.tsx +5 -37
  334. package/src/components/SavedFilterDropdown.tsx +0 -1
  335. package/src/components/SimpleTable/ScrollFrame.native.tsx +49 -0
  336. package/src/components/SimpleTable/ScrollFrame.tsx +18 -0
  337. package/src/components/SimpleTable/SimpleTable.stories.tsx +47 -0
  338. package/src/components/SimpleTable/columnSizing.spec.ts +73 -0
  339. package/src/components/SimpleTable/columnSizing.ts +39 -0
  340. package/src/components/SimpleTable/index.tsx +184 -112
  341. package/src/components/SimpleTable/simpleTable.spec.tsx +47 -19
  342. package/src/components/TableInput/RowDetailEditor.native.tsx +1 -3
  343. package/src/components/TableInput/RowDetailEditor.tsx +2 -10
  344. package/src/components/TableInput/index.native.tsx +3 -16
  345. package/src/components/TableInput/index.tsx +13 -24
  346. package/src/types.ts +7 -2
  347. package/types/components/ChildTable/index.d.ts +3 -1
  348. package/types/components/ChildTable/index.d.ts.map +1 -1
  349. package/types/components/DataTable/DataTableCardControls.d.ts +2 -3
  350. package/types/components/DataTable/DataTableCardControls.d.ts.map +1 -1
  351. package/types/components/DataTable/DataTableContext.d.ts +4 -4
  352. package/types/components/DataTable/DataTableContext.d.ts.map +1 -1
  353. package/types/components/DataTable/DataTableDocumentList.d.ts +7 -4
  354. package/types/components/DataTable/DataTableDocumentList.d.ts.map +1 -1
  355. package/types/components/DataTable/DataTableMobileCards.d.ts +1 -2
  356. package/types/components/DataTable/DataTableMobileCards.d.ts.map +1 -1
  357. package/types/components/DataTable/DataTableRoot.d.ts +1 -3
  358. package/types/components/DataTable/DataTableRoot.d.ts.map +1 -1
  359. package/types/components/DataTable/DataTableVirtualized.d.ts.map +1 -1
  360. package/types/components/DataTable/documentListSlots.d.ts +7 -4
  361. package/types/components/DataTable/documentListSlots.d.ts.map +1 -1
  362. package/types/components/DataTable/index.native.d.ts +1 -1
  363. package/types/components/DataTable/index.native.d.ts.map +1 -1
  364. package/types/components/DataTableCell/index.d.ts +1 -3
  365. package/types/components/DataTableCell/index.d.ts.map +1 -1
  366. package/types/components/DataTableColumnPinning/index.d.ts.map +1 -1
  367. package/types/components/DataTableFilters/index.d.ts +6 -1
  368. package/types/components/DataTableFilters/index.d.ts.map +1 -1
  369. package/types/components/DataTableGrouping/index.d.ts.map +1 -1
  370. package/types/components/DataTablePagination/index.d.ts +8 -1
  371. package/types/components/DataTablePagination/index.d.ts.map +1 -1
  372. package/types/components/DataTableToolbar/index.d.ts +0 -1
  373. package/types/components/DataTableToolbar/index.d.ts.map +1 -1
  374. package/types/components/DataTableViewOptions/index.d.ts +6 -1
  375. package/types/components/DataTableViewOptions/index.d.ts.map +1 -1
  376. package/types/components/KnobDialog.d.ts +0 -7
  377. package/types/components/KnobDialog.d.ts.map +1 -1
  378. package/types/components/SavedFilterDropdown.d.ts.map +1 -1
  379. package/types/components/SimpleTable/ScrollFrame.d.ts +10 -0
  380. package/types/components/SimpleTable/ScrollFrame.d.ts.map +1 -0
  381. package/types/components/SimpleTable/ScrollFrame.native.d.ts +10 -0
  382. package/types/components/SimpleTable/ScrollFrame.native.d.ts.map +1 -0
  383. package/types/components/SimpleTable/columnSizing.d.ts +24 -0
  384. package/types/components/SimpleTable/columnSizing.d.ts.map +1 -0
  385. package/types/components/SimpleTable/index.d.ts +6 -12
  386. package/types/components/SimpleTable/index.d.ts.map +1 -1
  387. package/types/components/TableInput/RowDetailEditor.d.ts +1 -2
  388. package/types/components/TableInput/RowDetailEditor.d.ts.map +1 -1
  389. package/types/components/TableInput/RowDetailEditor.native.d.ts +1 -1
  390. package/types/components/TableInput/RowDetailEditor.native.d.ts.map +1 -1
  391. package/types/components/TableInput/index.d.ts +1 -6
  392. package/types/components/TableInput/index.d.ts.map +1 -1
  393. package/types/components/TableInput/index.native.d.ts +1 -6
  394. package/types/components/TableInput/index.native.d.ts.map +1 -1
  395. package/types/types.d.ts +7 -2
  396. package/types/types.d.ts.map +1 -1
@@ -20,11 +20,16 @@ import {
20
20
  import { Button, Checkbox, Field, useFormField } from "@multiplatform.one/forms";
21
21
  import { flexRender } from "@tanstack/react-table";
22
22
  import { useVirtualizer } from "@tanstack/react-virtual";
23
- import { ensureFocusVisibleRing, useResolvedKnobs } from "@multiplatform.one/theme";
23
+ import {
24
+ ensureFocusVisibleRing,
25
+ sizeTokenBelow,
26
+ useResolvedKnobs,
27
+ Surface,
28
+ } from "@multiplatform.one/theme";
24
29
  import React, { useEffect, useRef, useMemo, useCallback, useState } from "react";
25
30
  import { AsyncBoundary, EmptyState, Tooltip, useDirection } from "@multiplatform.one/components";
26
- import type { FontSizeTokens } from "tamagui";
27
- import { Text, View, isWeb, useMedia } from "tamagui";
31
+ import type { FontSizeTokens, SizeTokens } from "tamagui";
32
+ import { SizableText, Text, View, isWeb, useMedia } from "tamagui";
28
33
  import { useTranslation } from "react-i18next";
29
34
  import { useDataTable } from "../../hooks/useDataTable";
30
35
  import { useDragScroll } from "../../hooks/useDragScroll";
@@ -90,8 +95,6 @@ export interface DataTableRootProps<
90
95
  > extends DataTableProps<TData> {
91
96
  /** Compound sub-components rendered as children */
92
97
  children?: React.ReactNode;
93
- /** Structural modifier: compact layout */
94
- compact?: boolean;
95
98
  /** Structural modifier: disabled state */
96
99
  disabled?: boolean;
97
100
  /** Structural intent — joins the resolver path (audit 16). */
@@ -164,7 +167,6 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
164
167
  renderFilters: _renderFilters,
165
168
  className,
166
169
  size,
167
- compact = false,
168
170
  disabled = false,
169
171
  accent,
170
172
  error,
@@ -183,10 +185,12 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
183
185
  const showList = layout === "list";
184
186
  const showCards = !showList && (layout === "cards" || (layout === "auto" && sm === false));
185
187
  const intent = resolveDataTableIntent({ accent, error, warning, success });
188
+ // `size` is a token: the toolbar, search, pagination, header filters and
189
+ // bulk bar render at it through the Surface below; cells one key below.
186
190
  const { knobProps, disabledState } = useResolvedKnobs({
187
191
  intent,
188
192
  component: "DataTable",
189
- compact,
193
+ size,
190
194
  });
191
195
  const chrome = dataTableChrome(String(knobProps.sizeToken));
192
196
  const rowHeightPx = chrome.rowPx;
@@ -269,10 +273,10 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
269
273
  }
270
274
  }, [selectAllScope, table]);
271
275
 
272
- const resolvedSize: "sm" | "md" | "lg" =
273
- size ?? (knobProps.sizeToken === "$3" ? "sm" : knobProps.sizeToken === "$5" ? "lg" : "md");
274
-
275
- const cellHeight = resolvedSize === "sm" ? "$3" : resolvedSize === "lg" ? "$5" : "$4";
276
+ const resolvedSize = knobProps.sizeToken as SizeTokens;
277
+ // Rows keep the table's height; the controls inside a cell sit one key below.
278
+ const cellHeight = resolvedSize;
279
+ const cellSize = sizeTokenBelow(resolvedSize);
276
280
 
277
281
  const headerGroups = table.getHeaderGroups();
278
282
  const rowModelRows = table.getRowModel().rows;
@@ -719,7 +723,6 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
719
723
  [readOnly, disabled, minRows, data, isFormMode, onDataChange],
720
724
  );
721
725
 
722
- const isCompact = resolvedSize === "sm" || compact;
723
726
  const renderCellContent = useCallback(
724
727
  (cell: any, rowIndex: number, rowData: TData) => {
725
728
  const columnDef = cell.column.columnDef as DataTableColumn;
@@ -779,21 +782,13 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
779
782
  columnLabel={typeof columnDef.header === "string" ? columnDef.header : undefined}
780
783
  rowIndex={rowIndex}
781
784
  rowData={rowData}
782
- size={knobProps.sizeToken}
783
- compact={isCompact}
785
+ size={String(cellSize)}
784
786
  linkedValue={linkedValue}
785
787
  onLinkedChange={onLinkedChange}
786
788
  />
787
789
  );
788
790
  },
789
- [
790
- handleCellChange,
791
- readOnly,
792
- disabled,
793
- knobProps.sizeToken,
794
- knobProps.label.fontSize,
795
- isCompact,
796
- ],
791
+ [handleCellChange, readOnly, disabled, cellSize, knobProps.label.fontSize],
797
792
  );
798
793
 
799
794
  const extraColumnsBefore =
@@ -921,7 +916,6 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
921
916
  // aria-label rides the role="checkbox" frame itself.
922
917
  "aria-label": deriveSelectRowLabel(row, rowIndex),
923
918
  }}
924
- compact={isCompact}
925
919
  />
926
920
  </Table.Cell>
927
921
  )}
@@ -1106,7 +1100,6 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1106
1100
  handleDeleteRow,
1107
1101
  data.length,
1108
1102
  minRows,
1109
- isCompact,
1110
1103
  t,
1111
1104
  deriveSelectRowLabel,
1112
1105
  ExpandCaretIcon,
@@ -1151,7 +1144,6 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1151
1144
  views: state.views,
1152
1145
  activeViewId: state.activeViewId,
1153
1146
  size: knobProps.sizeToken,
1154
- compact: isCompact,
1155
1147
  isFetching: Boolean(state.isFetching),
1156
1148
  });
1157
1149
  }
@@ -1163,12 +1155,7 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1163
1155
  onClearFilters={actions.clearFilters}
1164
1156
  customActions={
1165
1157
  defaultCardToolbar && hasCardSort ? (
1166
- <DataTableCardSortControl
1167
- table={table}
1168
- compact={isCompact}
1169
- disabled={disabled}
1170
- contained
1171
- />
1158
+ <DataTableCardSortControl table={table} disabled={disabled} contained />
1172
1159
  ) : undefined
1173
1160
  }
1174
1161
  activeFilterCount={activeFilterCount}
@@ -1180,7 +1167,6 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1180
1167
  enableGlobalSearch={enableGlobalSearch}
1181
1168
  enableFiltering={enableFiltering}
1182
1169
  size={knobProps.sizeToken}
1183
- compact={isCompact}
1184
1170
  isFetching={Boolean(state.isFetching)}
1185
1171
  />
1186
1172
  );
@@ -1201,7 +1187,7 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1201
1187
  pagination={state.pagination}
1202
1188
  onPaginationChange={actions.setPagination}
1203
1189
  pageSizeOptions={resolvedPageSizeOptions}
1204
- compact
1190
+ size={resolvedSize}
1205
1191
  />
1206
1192
  );
1207
1193
  };
@@ -1270,7 +1256,7 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1270
1256
  onRetry={state.error ? onRetry : infinite?.retry}
1271
1257
  layout="table"
1272
1258
  errorTitle={t("Couldn't load table")}
1273
- compact
1259
+ size={resolvedSize}
1274
1260
  aria-label={resolvedAriaLabel}
1275
1261
  />
1276
1262
  );
@@ -1285,7 +1271,7 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1285
1271
  }
1286
1272
 
1287
1273
  return (
1288
- <DataTableContext.Provider size={resolvedSize} compact={isCompact}>
1274
+ <DataTableContext.Provider size={resolvedSize}>
1289
1275
  <DataTableStateContext.Provider value={stateContextValue}>
1290
1276
  <View
1291
1277
  flexDirection="column"
@@ -1323,963 +1309,979 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
1323
1309
  : {})}
1324
1310
  {...props}
1325
1311
  >
1326
- {/* Toolbar. The width-100% wrapper is the LC-40 carrier for
1312
+ <Surface size={resolvedSize}>
1313
+ {/* Toolbar. The width-100% wrapper is the LC-40 carrier for
1327
1314
  chrome that has no `disabled` API of its own: under keepLabel
1328
1315
  the chrome fragment dims the region (interaction is already
1329
1316
  blocked by the root inert). */}
1330
- {hasToolbar && (
1331
- <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
1332
- {renderToolbarComponent()}
1333
- </View>
1334
- )}
1317
+ {hasToolbar && (
1318
+ <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
1319
+ {renderToolbarComponent()}
1320
+ </View>
1321
+ )}
1335
1322
 
1336
- {/* Active filter chips — visibility surface for ALL filters,
1323
+ {/* Active filter chips — visibility surface for ALL filters,
1337
1324
  including hidden-column filters (Axiom 6 HONEST STATE) */}
1338
- {enableFiltering && (
1339
- <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
1340
- <DataTableFilterChips />
1341
- </View>
1342
- )}
1343
-
1344
- {/* Auto selection toolbar (DG-TBL-02) — placement from house bulkBarPlacement */}
1345
- {enableRowSelection && bulkBarPlacement === "top" ? (
1346
- <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
1347
- <DataTableBulkActions
1348
- actions={resolvedBulkActions}
1349
- maxVisibleActions={5}
1350
- showSelectionCount
1351
- placement="top"
1352
- />
1353
- </View>
1354
- ) : null}
1325
+ {enableFiltering && (
1326
+ <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
1327
+ <DataTableFilterChips />
1328
+ </View>
1329
+ )}
1330
+
1331
+ {/* Auto selection toolbar (DG-TBL-02) — placement from house bulkBarPlacement */}
1332
+ {enableRowSelection && bulkBarPlacement === "top" ? (
1333
+ <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
1334
+ <DataTableBulkActions
1335
+ actions={resolvedBulkActions}
1336
+ maxVisibleActions={5}
1337
+ showSelectionCount
1338
+ placement="top"
1339
+ />
1340
+ </View>
1341
+ ) : null}
1355
1342
 
1356
- {/* Compound sub-components (children) */}
1357
- {children}
1343
+ {/* Compound sub-components (children) */}
1344
+ {children}
1358
1345
 
1359
- {/* Card List View (layout="cards" or auto below $sm) */}
1360
- {showList ? (
1361
- <DataTableDocumentList
1362
- tableRows={displayRows}
1363
- enableRowSelection={enableRowSelection}
1364
- disabled={disabled}
1365
- hasActiveFilters={computed.hasActiveFilters}
1366
- renderCellContent={renderCellContent}
1367
- compact={isCompact}
1368
- selectRowLabel={deriveSelectRowLabel}
1369
- queryInFlight={queryInFlight}
1370
- {...(rowPressActive ? { getRowPressProps } : {})}
1371
- />
1372
- ) : showCards ? (
1373
- <>
1374
- {/* Header affordances (sort / per-column filter) live in the
1375
- grid headers; the card list restores them here. */}
1376
- {!defaultCardToolbar && (
1377
- <DataTableCardControls
1378
- table={table}
1379
- enableSorting={enableSorting}
1380
- enableFiltering={enableFiltering}
1381
- availableColumns={cardFilterColumns}
1382
- compact={isCompact}
1383
- disabled={disabled}
1384
- />
1385
- )}
1386
- <DataTableMobileCards
1346
+ {/* Card List View (layout="cards" or auto below $sm) */}
1347
+ {showList ? (
1348
+ <DataTableDocumentList
1387
1349
  tableRows={displayRows}
1388
1350
  enableRowSelection={enableRowSelection}
1389
- showRowNumbers={showRowNumbers}
1390
- showDeleteRow={showDeleteRow}
1391
- readOnly={readOnly}
1392
1351
  disabled={disabled}
1393
- dataLength={tableData.length}
1394
- minRows={minRows}
1395
1352
  hasActiveFilters={computed.hasActiveFilters}
1396
1353
  renderCellContent={renderCellContent}
1397
- onDeleteRow={effectiveHandleDeleteRow}
1398
- selectAllChecked={selectAllChecked}
1399
- selectAllIndeterminate={selectAllIndeterminate}
1400
- onToggleSelectAll={toggleSelectAll}
1401
- compact={isCompact}
1402
1354
  selectRowLabel={deriveSelectRowLabel}
1403
1355
  queryInFlight={queryInFlight}
1404
1356
  {...(rowPressActive ? { getRowPressProps } : {})}
1405
1357
  />
1406
- </>
1407
- ) : (
1408
- /* Table View */
1409
- <View
1410
- ref={(node: any) => {
1411
- if (enableKeyboardNavigation && !isSSR && keyboardNav.containerRef) {
1412
- (keyboardNav.containerRef as any).current = node;
1358
+ ) : showCards ? (
1359
+ <>
1360
+ {/* Header affordances (sort / per-column filter) live in the
1361
+ grid headers; the card list restores them here. */}
1362
+ {!defaultCardToolbar && (
1363
+ <DataTableCardControls
1364
+ table={table}
1365
+ enableSorting={enableSorting}
1366
+ enableFiltering={enableFiltering}
1367
+ availableColumns={cardFilterColumns}
1368
+ disabled={disabled}
1369
+ />
1370
+ )}
1371
+ <DataTableMobileCards
1372
+ tableRows={displayRows}
1373
+ enableRowSelection={enableRowSelection}
1374
+ showRowNumbers={showRowNumbers}
1375
+ showDeleteRow={showDeleteRow}
1376
+ readOnly={readOnly}
1377
+ disabled={disabled}
1378
+ dataLength={tableData.length}
1379
+ minRows={minRows}
1380
+ hasActiveFilters={computed.hasActiveFilters}
1381
+ renderCellContent={renderCellContent}
1382
+ onDeleteRow={effectiveHandleDeleteRow}
1383
+ selectAllChecked={selectAllChecked}
1384
+ selectAllIndeterminate={selectAllIndeterminate}
1385
+ onToggleSelectAll={toggleSelectAll}
1386
+ selectRowLabel={deriveSelectRowLabel}
1387
+ queryInFlight={queryInFlight}
1388
+ {...(rowPressActive ? { getRowPressProps } : {})}
1389
+ />
1390
+ </>
1391
+ ) : (
1392
+ /* Table View */
1393
+ <View
1394
+ ref={(node: any) => {
1395
+ if (enableKeyboardNavigation && !isSSR && keyboardNav.containerRef) {
1396
+ (keyboardNav.containerRef as any).current = node;
1397
+ }
1398
+ if (scrollContainerRef) {
1399
+ (scrollContainerRef as any).current = node;
1400
+ }
1401
+ }}
1402
+ flexDirection="column"
1403
+ width="100%"
1404
+ // Grow 0 / shrink 1 / basis auto: the grid frame hugs its
1405
+ // rows and only compresses (into internal scroll) when the
1406
+ // parent is shorter. flexGrow 1 stretched the frame to fill
1407
+ // tall parents, painting a dead zone between the last row
1408
+ // and the frame's bottom border on short pages (the frame
1409
+ // claimed data area that held no data — Axiom 6/LC-37).
1410
+ flexGrow={0}
1411
+ flexShrink={1}
1412
+ flexBasis="auto"
1413
+ minHeight={0}
1414
+ // This View (the drag-scroll ref) is the horizontal scroll
1415
+ // container; the table inside floors at max-content so it
1416
+ // overflows here instead of panning the whole page. With
1417
+ // pinning it is the ONE scrollport sticky cells track.
1418
+ {...(hScroll ? { overflowX: "auto" as any } : {})}
1419
+ aria-label={withInterp(t("{{label}} content", { label: resolvedAriaLabel }), {
1420
+ label: resolvedAriaLabel,
1421
+ })}
1422
+ tabIndex={enableKeyboardNavigation && !isSSR ? 0 : undefined}
1423
+ {...({ "data-table-grid": "true" } as any)}
1424
+ onKeyDown={enableKeyboardNavigation && !isSSR ? handleGridKeyDown : undefined}
1425
+ onPress={
1426
+ enableKeyboardNavigation && !isSSR
1427
+ ? keyboardNav.handleContainerClick
1428
+ : undefined
1413
1429
  }
1414
- if (scrollContainerRef) {
1415
- (scrollContainerRef as any).current = node;
1430
+ onBlur={
1431
+ enableKeyboardNavigation && !isSSR ? keyboardNav.handleContainerBlur : undefined
1416
1432
  }
1417
- }}
1418
- flexDirection="column"
1419
- width="100%"
1420
- // Grow 0 / shrink 1 / basis auto: the grid frame hugs its
1421
- // rows and only compresses (into internal scroll) when the
1422
- // parent is shorter. flexGrow 1 stretched the frame to fill
1423
- // tall parents, painting a dead zone between the last row
1424
- // and the frame's bottom border on short pages (the frame
1425
- // claimed data area that held no data — Axiom 6/LC-37).
1426
- flexGrow={0}
1427
- flexShrink={1}
1428
- flexBasis="auto"
1429
- minHeight={0}
1430
- // This View (the drag-scroll ref) is the horizontal scroll
1431
- // container; the table inside floors at max-content so it
1432
- // overflows here instead of panning the whole page. With
1433
- // pinning it is the ONE scrollport sticky cells track.
1434
- {...(hScroll ? { overflowX: "auto" as any } : {})}
1435
- aria-label={withInterp(t("{{label}} content", { label: resolvedAriaLabel }), {
1436
- label: resolvedAriaLabel,
1437
- })}
1438
- tabIndex={enableKeyboardNavigation && !isSSR ? 0 : undefined}
1439
- {...({ "data-table-grid": "true" } as any)}
1440
- onKeyDown={enableKeyboardNavigation && !isSSR ? handleGridKeyDown : undefined}
1441
- onPress={
1442
- enableKeyboardNavigation && !isSSR ? keyboardNav.handleContainerClick : undefined
1443
- }
1444
- onBlur={
1445
- enableKeyboardNavigation && !isSSR ? keyboardNav.handleContainerBlur : undefined
1446
- }
1447
- >
1448
- <Table
1449
- displayMode={displayMode}
1450
- alignCells={{ x: "start", y: "center" }}
1451
- alignHeaderCells={{ x: "start", y: "center" }}
1452
- cellHeight={cellHeight}
1453
- borderTopLeftRadius={hasToolbar ? 0 : knobProps.borderRadiusOuter.borderRadius}
1454
- borderTopRightRadius={hasToolbar ? 0 : knobProps.borderRadiusOuter.borderRadius}
1455
- borderBottomLeftRadius={knobProps.borderRadiusOuter.borderRadius}
1456
- borderBottomRightRadius={knobProps.borderRadiusOuter.borderRadius}
1457
- marginBottom={0}
1458
- aria-label={resolvedAriaLabel}
1459
- aria-rowcount={computed.totalPages * state.pagination.pageSize}
1460
- aria-colcount={
1461
- table.getVisibleLeafColumns().length + extraColumnsBefore + extraColumnsAfter
1462
- }
1463
- width="100%"
1464
- {...(hScroll ? { style: { minWidth: "max-content" } } : {})}
1465
- // Pinning: the Table must NOT be a scroll container (its
1466
- // overflow:hidden base makes it one) or sticky cells stick
1467
- // to it instead of the scrolling content View. Content
1468
- // fits the max-content box, so nothing needs the clip.
1469
- {...(hScroll && enableColumnPinning ? { overflow: "visible" as any } : {})}
1470
- // Roving-focus DOM scope for onRowPress arrow keys (LC-49).
1471
- {...(rowPressActive ? ({ "data-row-press-scope": "true" } as any) : {})}
1472
1433
  >
1473
- {/* Table Header */}
1474
- <Table.Head zIndex="$1" aria-label={t("Table headers")}>
1475
- {headerGroups.map((headerGroup: any) => {
1476
- rowCounter.current++;
1477
- return (
1478
- <Table.Row
1479
- key={headerGroup.id}
1480
- {...({
1481
- background: true,
1482
- backgroundColor: "$color2",
1483
- rowLocation:
1484
- rowCounter.current === 0
1485
- ? "first"
1486
- : rowCounter.current === allRowsLength - 1
1487
- ? "last"
1488
- : "middle",
1489
- borderTopRightRadius: hasToolbar
1490
- ? "$0"
1491
- : knobProps.borderRadiusOuter.borderRadius,
1492
- borderTopLeftRadius: hasToolbar
1493
- ? "$0"
1494
- : knobProps.borderRadiusOuter.borderRadius,
1495
- borderBottomLeftRadius: "$0",
1496
- borderBottomRightRadius: "$0",
1497
- "aria-rowindex": rowCounter.current,
1498
- } as any)}
1499
- >
1500
- {enableRowSelection && (
1501
- <Table.HeaderCell
1502
- cellWidth={selectionColWidth}
1503
- cellHeight={cellHeight as any}
1504
- cellLocation="first"
1505
- justifyContent="center"
1506
- >
1507
- <Checkbox
1508
- checked={
1509
- selectAllIndeterminate ? "indeterminate" : selectAllChecked
1510
- }
1511
- disabled={disabled}
1512
- onChange={(checked) => {
1513
- if (disabled || checked === "indeterminate") return;
1514
- const shouldSelect = checked === true;
1515
- const isAll =
1516
- selectAllScope === "filtered"
1517
- ? table.getIsAllRowsSelected()
1518
- : table.getIsAllPageRowsSelected();
1519
- if (shouldSelect !== isAll) toggleSelectAll();
1520
- }}
1521
- checkboxProps={{
1522
- "aria-label":
1523
- selectAllScope === "filtered"
1524
- ? t("Select all matching rows")
1525
- : t("Select all rows on page"),
1526
- }}
1527
- compact={isCompact}
1528
- />
1529
- </Table.HeaderCell>
1530
- )}
1531
-
1532
- {showRowNumbers && (
1533
- <Table.HeaderCell
1534
- cellWidth={chrome.rowNumberCol}
1535
- cellHeight={cellHeight as any}
1536
- cellLocation={enableRowSelection ? "middle" : "first"}
1537
- >
1538
- <Text fontSize={knobProps.sizeToken} fontWeight="600">
1539
- #
1540
- </Text>
1541
- </Table.HeaderCell>
1542
- )}
1543
-
1544
- {enableRowExpansion && (
1545
- <Table.HeaderCell
1546
- cellWidth={chrome.expandCol}
1547
- cellHeight={cellHeight as any}
1548
- cellLocation={
1549
- enableRowSelection || showRowNumbers ? "middle" : "first"
1550
- }
1551
- >
1552
- <View width={14} />
1553
- </Table.HeaderCell>
1554
- )}
1434
+ <Table
1435
+ size={resolvedSize}
1436
+ cellSize={cellSize}
1437
+ displayMode={displayMode}
1438
+ alignCells={{ x: "start", y: "center" }}
1439
+ alignHeaderCells={{ x: "start", y: "center" }}
1440
+ cellHeight={cellHeight}
1441
+ borderTopLeftRadius={hasToolbar ? 0 : knobProps.borderRadiusOuter.borderRadius}
1442
+ borderTopRightRadius={hasToolbar ? 0 : knobProps.borderRadiusOuter.borderRadius}
1443
+ borderBottomLeftRadius={knobProps.borderRadiusOuter.borderRadius}
1444
+ borderBottomRightRadius={knobProps.borderRadiusOuter.borderRadius}
1445
+ marginBottom={0}
1446
+ aria-label={resolvedAriaLabel}
1447
+ aria-rowcount={computed.totalPages * state.pagination.pageSize}
1448
+ aria-colcount={
1449
+ table.getVisibleLeafColumns().length + extraColumnsBefore + extraColumnsAfter
1450
+ }
1451
+ width="100%"
1452
+ {...(hScroll ? { style: { minWidth: "max-content" } } : {})}
1453
+ // Pinning: the Table must NOT be a scroll container (its
1454
+ // overflow:hidden base makes it one) or sticky cells stick
1455
+ // to it instead of the scrolling content View. Content
1456
+ // fits the max-content box, so nothing needs the clip.
1457
+ {...(hScroll && enableColumnPinning ? { overflow: "visible" as any } : {})}
1458
+ // Roving-focus DOM scope for onRowPress arrow keys (LC-49).
1459
+ {...(rowPressActive ? ({ "data-row-press-scope": "true" } as any) : {})}
1460
+ >
1461
+ {/* Table Header */}
1462
+ <Table.Head zIndex="$1" aria-label={t("Table headers")}>
1463
+ {headerGroups.map((headerGroup: any) => {
1464
+ rowCounter.current++;
1465
+ return (
1466
+ <Table.Row
1467
+ key={headerGroup.id}
1468
+ {...({
1469
+ background: true,
1470
+ backgroundColor: "$color2",
1471
+ rowLocation:
1472
+ rowCounter.current === 0
1473
+ ? "first"
1474
+ : rowCounter.current === allRowsLength - 1
1475
+ ? "last"
1476
+ : "middle",
1477
+ borderTopRightRadius: hasToolbar
1478
+ ? "$0"
1479
+ : knobProps.borderRadiusOuter.borderRadius,
1480
+ borderTopLeftRadius: hasToolbar
1481
+ ? "$0"
1482
+ : knobProps.borderRadiusOuter.borderRadius,
1483
+ borderBottomLeftRadius: "$0",
1484
+ borderBottomRightRadius: "$0",
1485
+ "aria-rowindex": rowCounter.current,
1486
+ } as any)}
1487
+ >
1488
+ {enableRowSelection && (
1489
+ <Table.HeaderCell
1490
+ cellWidth={selectionColWidth}
1491
+ cellHeight={cellHeight as any}
1492
+ cellLocation="first"
1493
+ justifyContent="center"
1494
+ >
1495
+ <Checkbox
1496
+ checked={
1497
+ selectAllIndeterminate ? "indeterminate" : selectAllChecked
1498
+ }
1499
+ disabled={disabled}
1500
+ onChange={(checked) => {
1501
+ if (disabled || checked === "indeterminate") return;
1502
+ const shouldSelect = checked === true;
1503
+ const isAll =
1504
+ selectAllScope === "filtered"
1505
+ ? table.getIsAllRowsSelected()
1506
+ : table.getIsAllPageRowsSelected();
1507
+ if (shouldSelect !== isAll) toggleSelectAll();
1508
+ }}
1509
+ checkboxProps={{
1510
+ "aria-label":
1511
+ selectAllScope === "filtered"
1512
+ ? t("Select all matching rows")
1513
+ : t("Select all rows on page"),
1514
+ }}
1515
+ />
1516
+ </Table.HeaderCell>
1517
+ )}
1555
1518
 
1556
- {headerGroup.headers.map((header: any, headerIndex: number) => {
1557
- const isSortableHeader = header.column.getCanSort();
1558
- const sortDirection = header.column.getIsSorted();
1559
- const canResize = enableColumnResizing && header.column.getCanResize();
1560
- const resizeHandler = canResize ? header.getResizeHandler() : undefined;
1561
- const colSize = header.getSize();
1562
- const colMinSize = header.column.columnDef.minSize ?? 0;
1563
- const colMaxSize =
1564
- header.column.columnDef.maxSize ?? Number.MAX_SAFE_INTEGER;
1565
- const stickyStyle = getStickyStyle(header.column.id);
1566
- const columnDef = header.column.columnDef as DataTableColumn;
1567
- const columnAlign = resolveColumnAlign({
1568
- ...columnDef,
1569
- id: header.column.id,
1570
- });
1571
- const headerJustify = alignToFlex(columnAlign);
1572
- const isRightAligned = columnAlign === "right";
1573
-
1574
- const isFirstHeaderCell =
1575
- headerIndex === 0 &&
1576
- !enableRowSelection &&
1577
- !showRowNumbers &&
1578
- !enableRowExpansion;
1579
- const isLastHeaderCell =
1580
- headerIndex === headerGroup.headers.length - 1 &&
1581
- !(showDeleteRow && !readOnly);
1582
- const headerCellLocation = isFirstHeaderCell
1583
- ? "first"
1584
- : isLastHeaderCell
1585
- ? "last"
1586
- : "middle";
1519
+ {showRowNumbers && (
1520
+ <Table.HeaderCell
1521
+ cellWidth={chrome.rowNumberCol}
1522
+ cellHeight={cellHeight as any}
1523
+ cellLocation={enableRowSelection ? "middle" : "first"}
1524
+ >
1525
+ <Text fontSize={knobProps.sizeToken} fontWeight="600">
1526
+ #
1527
+ </Text>
1528
+ </Table.HeaderCell>
1529
+ )}
1587
1530
 
1588
- return (
1531
+ {enableRowExpansion && (
1589
1532
  <Table.HeaderCell
1590
- key={header.id}
1591
- id={`${header.column.id}-header`}
1592
- onPress={
1593
- isSortableHeader && !disabled
1594
- ? header.column.getToggleSortingHandler()
1595
- : undefined
1596
- }
1597
- // Keyboard operability (WCAG 2.1.1): the sort
1598
- // control must not be mouse-only — Tab reaches
1599
- // sortable headers, Enter/Space toggles (Shift
1600
- // held = multi-sort, same as shift+click).
1601
- // Disabled tables drop the handlers (the root
1602
- // inert already blocks focus on web).
1603
- {...(isSortableHeader && !disabled && isWeb
1604
- ? ({
1605
- tabIndex: 0,
1606
- onKeyDown: (e: React.KeyboardEvent) => {
1607
- if (
1608
- e.key === "Enter" ||
1609
- e.key === " " ||
1610
- e.key === "Spacebar"
1611
- ) {
1612
- e.preventDefault();
1613
- header.column.getToggleSortingHandler()?.(e);
1614
- }
1615
- },
1616
- focusVisibleStyle: ensureFocusVisibleRing({
1617
- outlineOffset: -2,
1618
- }),
1619
- } as any)
1620
- : {})}
1621
- cursor={
1622
- disabled
1623
- ? "not-allowed"
1624
- : isSortableHeader
1625
- ? "pointer"
1626
- : "default"
1627
- }
1628
- position="relative"
1629
- cellLocation={headerCellLocation}
1630
- justifyContent={headerJustify}
1631
- data-align={columnAlign}
1632
- aria-sort={
1633
- isSortableHeader
1634
- ? sortDirection === "asc"
1635
- ? "ascending"
1636
- : sortDirection === "desc"
1637
- ? "descending"
1638
- : "none"
1639
- : undefined
1533
+ cellWidth={chrome.expandCol}
1534
+ cellHeight={cellHeight as any}
1535
+ cellLocation={
1536
+ enableRowSelection || showRowNumbers ? "middle" : "first"
1640
1537
  }
1641
- {...(dnd && !disabled
1642
- ? ({
1643
- draggable: true,
1644
- onDragStart: (e: React.DragEvent<HTMLElement>) =>
1645
- dnd.onDragStart(e, header.column.id),
1646
- onDragOver: dnd.onDragOver,
1647
- onDrop: (e: React.DragEvent<HTMLElement>) =>
1648
- dnd.onDrop(e, header.column.id),
1649
- } as any)
1650
- : {})}
1651
- {...cellFlexProps}
1652
- {...getColSizeProps(header.column)}
1653
- {...(isWeb && stickyStyle
1654
- ? {
1655
- style: {
1656
- position: "sticky",
1657
- ...("insetInlineStart" in stickyStyle && {
1658
- insetInlineStart: stickyStyle.insetInlineStart,
1659
- }),
1660
- ...("insetInlineEnd" in stickyStyle && {
1661
- insetInlineEnd: (stickyStyle as any).insetInlineEnd,
1662
- }),
1663
- zIndex: 2,
1664
- backgroundColor: "var(--color2)",
1665
- } as React.CSSProperties,
1666
- }
1667
- : {})}
1668
1538
  >
1669
- {/* LC-10 (MPO-336): only the label yields
1539
+ <View width={14} />
1540
+ </Table.HeaderCell>
1541
+ )}
1542
+
1543
+ {headerGroup.headers.map((header: any, headerIndex: number) => {
1544
+ const isSortableHeader = header.column.getCanSort();
1545
+ const sortDirection = header.column.getIsSorted();
1546
+ const canResize =
1547
+ enableColumnResizing && header.column.getCanResize();
1548
+ const resizeHandler = canResize
1549
+ ? header.getResizeHandler()
1550
+ : undefined;
1551
+ const colSize = header.getSize();
1552
+ const colMinSize = header.column.columnDef.minSize ?? 0;
1553
+ const colMaxSize =
1554
+ header.column.columnDef.maxSize ?? Number.MAX_SAFE_INTEGER;
1555
+ const stickyStyle = getStickyStyle(header.column.id);
1556
+ const columnDef = header.column.columnDef as DataTableColumn;
1557
+ const columnAlign = resolveColumnAlign({
1558
+ ...columnDef,
1559
+ id: header.column.id,
1560
+ });
1561
+ const headerJustify = alignToFlex(columnAlign);
1562
+ const isRightAligned = columnAlign === "right";
1563
+
1564
+ const isFirstHeaderCell =
1565
+ headerIndex === 0 &&
1566
+ !enableRowSelection &&
1567
+ !showRowNumbers &&
1568
+ !enableRowExpansion;
1569
+ const isLastHeaderCell =
1570
+ headerIndex === headerGroup.headers.length - 1 &&
1571
+ !(showDeleteRow && !readOnly);
1572
+ const headerCellLocation = isFirstHeaderCell
1573
+ ? "first"
1574
+ : isLastHeaderCell
1575
+ ? "last"
1576
+ : "middle";
1577
+
1578
+ return (
1579
+ <Table.HeaderCell
1580
+ key={header.id}
1581
+ id={`${header.column.id}-header`}
1582
+ onPress={
1583
+ isSortableHeader && !disabled
1584
+ ? header.column.getToggleSortingHandler()
1585
+ : undefined
1586
+ }
1587
+ // Keyboard operability (WCAG 2.1.1): the sort
1588
+ // control must not be mouse-only — Tab reaches
1589
+ // sortable headers, Enter/Space toggles (Shift
1590
+ // held = multi-sort, same as shift+click).
1591
+ // Disabled tables drop the handlers (the root
1592
+ // inert already blocks focus on web).
1593
+ {...(isSortableHeader && !disabled && isWeb
1594
+ ? ({
1595
+ tabIndex: 0,
1596
+ onKeyDown: (e: React.KeyboardEvent) => {
1597
+ if (
1598
+ e.key === "Enter" ||
1599
+ e.key === " " ||
1600
+ e.key === "Spacebar"
1601
+ ) {
1602
+ e.preventDefault();
1603
+ header.column.getToggleSortingHandler()?.(e);
1604
+ }
1605
+ },
1606
+ focusVisibleStyle: ensureFocusVisibleRing({
1607
+ outlineOffset: -2,
1608
+ }),
1609
+ } as any)
1610
+ : {})}
1611
+ cursor={
1612
+ disabled
1613
+ ? "not-allowed"
1614
+ : isSortableHeader
1615
+ ? "pointer"
1616
+ : "default"
1617
+ }
1618
+ position="relative"
1619
+ cellLocation={headerCellLocation}
1620
+ justifyContent={headerJustify}
1621
+ data-align={columnAlign}
1622
+ aria-sort={
1623
+ isSortableHeader
1624
+ ? sortDirection === "asc"
1625
+ ? "ascending"
1626
+ : sortDirection === "desc"
1627
+ ? "descending"
1628
+ : "none"
1629
+ : undefined
1630
+ }
1631
+ {...(dnd && !disabled
1632
+ ? ({
1633
+ draggable: true,
1634
+ onDragStart: (e: React.DragEvent<HTMLElement>) =>
1635
+ dnd.onDragStart(e, header.column.id),
1636
+ onDragOver: dnd.onDragOver,
1637
+ onDrop: (e: React.DragEvent<HTMLElement>) =>
1638
+ dnd.onDrop(e, header.column.id),
1639
+ } as any)
1640
+ : {})}
1641
+ {...cellFlexProps}
1642
+ {...getColSizeProps(header.column)}
1643
+ {...(isWeb && stickyStyle
1644
+ ? {
1645
+ style: {
1646
+ position: "sticky",
1647
+ ...("insetInlineStart" in stickyStyle && {
1648
+ insetInlineStart: stickyStyle.insetInlineStart,
1649
+ }),
1650
+ ...("insetInlineEnd" in stickyStyle && {
1651
+ insetInlineEnd: (stickyStyle as any).insetInlineEnd,
1652
+ }),
1653
+ zIndex: 2,
1654
+ backgroundColor: "var(--color2)",
1655
+ } as React.CSSProperties,
1656
+ }
1657
+ : {})}
1658
+ >
1659
+ {/* LC-10 (MPO-336): only the label yields
1670
1660
  to a narrow column; the glyphs keep their
1671
1661
  size or they paint into the next one. The
1672
1662
  filter cluster wraps under the label first,
1673
1663
  so the label keeps the column's width. */}
1674
- <View
1675
- flexDirection="row"
1676
- flexWrap="wrap"
1677
- gap="$2"
1678
- alignItems="center"
1679
- justifyContent={isRightAligned ? "flex-end" : "space-between"}
1680
- flex={1}
1681
- minWidth={0}
1682
- >
1683
1664
  <View
1684
1665
  flexDirection="row"
1666
+ flexWrap="wrap"
1685
1667
  gap="$2"
1686
1668
  alignItems="center"
1687
- flexGrow={isRightAligned ? 0 : 1}
1688
- flexShrink={1}
1689
- flexBasis="auto"
1669
+ justifyContent={isRightAligned ? "flex-end" : "space-between"}
1670
+ flex={1}
1690
1671
  minWidth={0}
1691
- justifyContent={isRightAligned ? "flex-end" : undefined}
1692
1672
  >
1693
- <Text
1694
- fontSize={knobProps.sizeToken}
1695
- userSelect="none"
1673
+ <View
1674
+ flexDirection="row"
1675
+ gap="$2"
1676
+ alignItems="center"
1677
+ flexGrow={isRightAligned ? 0 : 1}
1696
1678
  flexShrink={1}
1679
+ flexBasis="auto"
1697
1680
  minWidth={0}
1698
- textAlign={isRightAligned ? "right" : undefined}
1699
- data-header-label=""
1700
- {...(isWeb ? { style: { overflowWrap: "anywhere" } } : {})}
1681
+ justifyContent={isRightAligned ? "flex-end" : undefined}
1701
1682
  >
1702
- {header.isPlaceholder
1703
- ? null
1704
- : flexRender(
1705
- header.column.columnDef.header,
1706
- header.getContext(),
1707
- )}
1708
- </Text>
1709
- {isSortableHeader && (
1710
- <Tooltip
1711
- content={
1712
- sortDirection === "asc"
1713
- ? t("Sorted ascending (click to sort descending)")
1714
- : sortDirection === "desc"
1715
- ? t("Sorted descending (click to clear)")
1716
- : t("Click to sort (Shift+click for multi-sort)")
1717
- }
1683
+ <Text
1684
+ fontSize={knobProps.sizeToken}
1685
+ userSelect="none"
1686
+ flexShrink={1}
1687
+ minWidth={0}
1688
+ textAlign={isRightAligned ? "right" : undefined}
1689
+ data-header-label=""
1690
+ {...(isWeb ? { style: { overflowWrap: "anywhere" } } : {})}
1718
1691
  >
1719
- <View aria-hidden={true} role="presentation" flexShrink={0}>
1720
- {sortDirection === "asc" && (
1721
- <CaretDownIcon
1722
- size={chrome.iconPx}
1723
- color="var(--color11)"
1724
- />
1725
- )}
1726
- {sortDirection === "desc" && (
1727
- <CaretDownIcon
1728
- size={chrome.iconPx}
1729
- color="var(--color11)"
1730
- style={{ transform: "rotate(180deg)" }}
1731
- />
1732
- )}
1733
- {sortDirection === false && (
1734
- <CaretUpDownIcon
1735
- size={chrome.iconPx}
1736
- color="var(--color11)"
1737
- />
1692
+ {header.isPlaceholder
1693
+ ? null
1694
+ : flexRender(
1695
+ header.column.columnDef.header,
1696
+ header.getContext(),
1697
+ )}
1698
+ </Text>
1699
+ {isSortableHeader && (
1700
+ <Tooltip
1701
+ content={
1702
+ sortDirection === "asc"
1703
+ ? t("Sorted ascending (click to sort descending)")
1704
+ : sortDirection === "desc"
1705
+ ? t("Sorted descending (click to clear)")
1706
+ : t("Click to sort (Shift+click for multi-sort)")
1707
+ }
1708
+ >
1709
+ <View
1710
+ aria-hidden={true}
1711
+ role="presentation"
1712
+ flexShrink={0}
1713
+ >
1714
+ {sortDirection === "asc" && (
1715
+ <CaretDownIcon
1716
+ size={chrome.iconPx}
1717
+ color="var(--color11)"
1718
+ />
1719
+ )}
1720
+ {sortDirection === "desc" && (
1721
+ <CaretDownIcon
1722
+ size={chrome.iconPx}
1723
+ color="var(--color11)"
1724
+ style={{ transform: "rotate(180deg)" }}
1725
+ />
1726
+ )}
1727
+ {sortDirection === false && (
1728
+ <CaretUpDownIcon
1729
+ size={chrome.iconPx}
1730
+ color="var(--color11)"
1731
+ />
1732
+ )}
1733
+ </View>
1734
+ </Tooltip>
1735
+ )}
1736
+ </View>
1737
+ <View
1738
+ flexDirection="row"
1739
+ gap="$1"
1740
+ alignItems="center"
1741
+ flexShrink={0}
1742
+ >
1743
+ {enableFiltering && header.column.getCanFilter() && (
1744
+ <ColumnHeaderFilter
1745
+ columnId={header.column.id}
1746
+ columnLabel={
1747
+ typeof header.column.columnDef.header === "string"
1748
+ ? header.column.columnDef.header
1749
+ : header.column.id
1750
+ }
1751
+ columnType={mapFieldToFilterType(
1752
+ getColumnField(
1753
+ header.column.columnDef as DataTableColumn,
1754
+ ),
1738
1755
  )}
1739
- </View>
1740
- </Tooltip>
1741
- )}
1742
- </View>
1743
- <View
1744
- flexDirection="row"
1745
- gap="$1"
1746
- alignItems="center"
1747
- flexShrink={0}
1748
- >
1749
- {enableFiltering && header.column.getCanFilter() && (
1750
- <ColumnHeaderFilter
1751
- columnId={header.column.id}
1752
- columnLabel={
1753
- typeof header.column.columnDef.header === "string"
1754
- ? header.column.columnDef.header
1755
- : header.column.id
1756
- }
1757
- columnType={mapFieldToFilterType(
1758
- getColumnField(
1759
- header.column.columnDef as DataTableColumn,
1760
- ),
1761
- )}
1762
- filterValue={header.column.getFilterValue()}
1763
- onFilterChange={(value) =>
1764
- header.column.setFilterValue(value)
1765
- }
1766
- isFiltered={header.column.getIsFiltered()}
1767
- options={
1768
- (header.column.columnDef as any).fieldProps?.options
1769
- }
1770
- />
1771
- )}
1772
- {pinning && enableColumnPinning && (
1773
- /* One compact cycle control per header
1756
+ filterValue={header.column.getFilterValue()}
1757
+ onFilterChange={(value) =>
1758
+ header.column.setFilterValue(value)
1759
+ }
1760
+ isFiltered={header.column.getIsFiltered()}
1761
+ options={
1762
+ (header.column.columnDef as any).fieldProps?.options
1763
+ }
1764
+ />
1765
+ )}
1766
+ {pinning && enableColumnPinning && (
1767
+ /* One compact cycle control per header
1774
1768
  (left → right → unpin) — two full
1775
1769
  buttons crowded the header (owner). */
1776
- <pinning.PinButton columnId={header.column.id} />
1777
- )}
1770
+ <pinning.PinButton columnId={header.column.id} />
1771
+ )}
1772
+ </View>
1778
1773
  </View>
1779
- </View>
1780
- {canResize && resizeHandler && (
1781
- <View
1782
- position="absolute"
1783
- right={-4}
1784
- top={0}
1785
- height={2000}
1786
- width={8}
1787
- cursor="col-resize"
1788
- onMouseDown={resizeHandler as any}
1789
- onTouchStart={resizeHandler as any}
1790
- role="separator"
1791
- aria-valuenow={colSize}
1792
- aria-valuemin={colMinSize}
1793
- aria-valuemax={colMaxSize}
1794
- aria-label={withInterp(
1795
- t("Resize {{column}} column", {
1796
- column: header.column.columnDef.header || header.column.id,
1797
- }),
1798
- {
1799
- column: header.column.columnDef.header || header.column.id,
1800
- },
1801
- )}
1802
- style={{ touchAction: "none" }}
1803
- zIndex={10}
1804
- />
1805
- )}
1806
- </Table.HeaderCell>
1807
- );
1808
- })}
1774
+ {canResize && resizeHandler && (
1775
+ <View
1776
+ position="absolute"
1777
+ right={-4}
1778
+ top={0}
1779
+ height={2000}
1780
+ width={8}
1781
+ cursor="col-resize"
1782
+ onMouseDown={resizeHandler as any}
1783
+ onTouchStart={resizeHandler as any}
1784
+ role="separator"
1785
+ aria-valuenow={colSize}
1786
+ aria-valuemin={colMinSize}
1787
+ aria-valuemax={colMaxSize}
1788
+ aria-label={withInterp(
1789
+ t("Resize {{column}} column", {
1790
+ column:
1791
+ header.column.columnDef.header || header.column.id,
1792
+ }),
1793
+ {
1794
+ column:
1795
+ header.column.columnDef.header || header.column.id,
1796
+ },
1797
+ )}
1798
+ style={{ touchAction: "none" }}
1799
+ zIndex={10}
1800
+ />
1801
+ )}
1802
+ </Table.HeaderCell>
1803
+ );
1804
+ })}
1809
1805
 
1810
- {showDeleteRow && !readOnly && (
1811
- <Table.HeaderCell
1812
- cellWidth={chrome.deleteCol}
1813
- cellHeight={cellHeight as any}
1814
- cellLocation="last"
1815
- />
1816
- )}
1806
+ {showDeleteRow && !readOnly && (
1807
+ <Table.HeaderCell
1808
+ cellWidth={chrome.deleteCol}
1809
+ cellHeight={cellHeight as any}
1810
+ cellLocation="last"
1811
+ />
1812
+ )}
1813
+ </Table.Row>
1814
+ );
1815
+ })}
1816
+ </Table.Head>
1817
+
1818
+ {/* Table Body */}
1819
+ <Table.Body
1820
+ // Virtualized mode hosts a div rowgroup (DataTableVirtualized)
1821
+ // inside a tbody>tr>td bridge; presentation-ing the bridge
1822
+ // keeps the AT grid tree clean: table > rowgroup(thead) +
1823
+ // rowgroup(virtual rows) with no cell-wrapping-rowgroup
1824
+ // noise. aria-label is prohibited on presentation roles.
1825
+ role={isVirtualized ? "presentation" : "rowgroup"}
1826
+ aria-label={isVirtualized ? undefined : t("Table data")}
1827
+ // Pinning: the flex-variant overflowY:auto computes
1828
+ // overflow-x:auto, making the body its own horizontal
1829
+ // scroller — headers (outside it) then never move with
1830
+ // the columns. Visible keeps the sticky chain clean so
1831
+ // the content View is the one scrollport.
1832
+ {...(hScroll && enableColumnPinning
1833
+ ? { overflowY: "visible" as any, overflowX: "visible" as any }
1834
+ : {})}
1835
+ ref={(node: any) => {
1836
+ tableBodyRef.current = node ?? null;
1837
+ }}
1838
+ >
1839
+ {displayRows.length === 0 ? (
1840
+ <Table.Row>
1841
+ <Table.Cell>
1842
+ {isRefetching ? null : (
1843
+ <EmptyState
1844
+ size={resolvedSize}
1845
+ aria-live="polite"
1846
+ title={
1847
+ computed.hasActiveFilters
1848
+ ? t("No results found")
1849
+ : t("No data available")
1850
+ }
1851
+ />
1852
+ )}
1853
+ </Table.Cell>
1817
1854
  </Table.Row>
1818
- );
1819
- })}
1820
- </Table.Head>
1821
-
1822
- {/* Table Body */}
1823
- <Table.Body
1824
- // Virtualized mode hosts a div rowgroup (DataTableVirtualized)
1825
- // inside a tbody>tr>td bridge; presentation-ing the bridge
1826
- // keeps the AT grid tree clean: table > rowgroup(thead) +
1827
- // rowgroup(virtual rows) with no cell-wrapping-rowgroup
1828
- // noise. aria-label is prohibited on presentation roles.
1829
- role={isVirtualized ? "presentation" : "rowgroup"}
1830
- aria-label={isVirtualized ? undefined : t("Table data")}
1831
- // Pinning: the flex-variant overflowY:auto computes
1832
- // overflow-x:auto, making the body its own horizontal
1833
- // scroller — headers (outside it) then never move with
1834
- // the columns. Visible keeps the sticky chain clean so
1835
- // the content View is the one scrollport.
1836
- {...(hScroll && enableColumnPinning
1837
- ? { overflowY: "visible" as any, overflowX: "visible" as any }
1838
- : {})}
1839
- ref={(node: any) => {
1840
- tableBodyRef.current = node ?? null;
1841
- }}
1842
- >
1843
- {displayRows.length === 0 ? (
1844
- <Table.Row>
1845
- <Table.Cell>
1846
- {isRefetching ? null : (
1847
- <EmptyState
1848
- compact
1849
- aria-live="polite"
1850
- title={
1851
- computed.hasActiveFilters
1852
- ? t("No results found")
1853
- : t("No data available")
1854
- }
1855
+ ) : isVirtualized ? (
1856
+ <Table.Row role="presentation">
1857
+ <Table.Cell
1858
+ role="presentation"
1859
+ padding={0}
1860
+ // In the default flex displayMode colSpan is inert
1861
+ // and the context default gives cells a fixed token
1862
+ // width — the virtualized body must fill the row
1863
+ // explicitly or it collapses to that token. (In the
1864
+ // real-<table> displayMode the colSpan attribute
1865
+ // now genuinely spans.)
1866
+ cellWidth="auto"
1867
+ style={
1868
+ {
1869
+ display: "block",
1870
+ overflow: "hidden",
1871
+ width: "100%",
1872
+ minWidth: 0,
1873
+ } as any
1874
+ }
1875
+ {...({
1876
+ colSpan:
1877
+ table.getVisibleLeafColumns().length +
1878
+ extraColumnsBefore +
1879
+ extraColumnsAfter,
1880
+ } as any)}
1881
+ >
1882
+ <DataTableVirtualized
1883
+ virtualItems={virtualItems}
1884
+ totalSize={totalSize}
1885
+ bodyScrollRef={bodyScrollRef}
1886
+ virtualizationHeight={virtualizationHeight}
1887
+ tableRows={displayRows}
1888
+ headerGroups={headerGroups}
1889
+ showRowNumbers={showRowNumbers}
1890
+ enableRowExpansion={enableRowExpansion}
1891
+ showDeleteRow={showDeleteRow}
1892
+ readOnly={readOnly}
1893
+ enableKeyboardNavigation={enableKeyboardNavigation}
1894
+ keyboardNav={keyboardNav}
1895
+ getColSizeProps={getColSizeProps}
1896
+ renderRowContent={renderRowContent}
1897
+ extraColumnsBefore={extraColumnsBefore}
1898
+ extraColumnsAfter={extraColumnsAfter}
1899
+ table={table}
1900
+ hasInfiniteTail={hasInfiniteTail}
1901
+ rowHeightPx={rowHeightPx}
1902
+ tableZebraOn={tableZebraOn}
1903
+ {...(rowPressActive ? { getRowPressProps } : {})}
1855
1904
  />
1856
- )}
1857
- </Table.Cell>
1858
- </Table.Row>
1859
- ) : isVirtualized ? (
1860
- <Table.Row role="presentation">
1861
- <Table.Cell
1862
- role="presentation"
1863
- padding={0}
1864
- // In the default flex displayMode colSpan is inert
1865
- // and the context default gives cells a fixed token
1866
- // width — the virtualized body must fill the row
1867
- // explicitly or it collapses to that token. (In the
1868
- // real-<table> displayMode the colSpan attribute
1869
- // now genuinely spans.)
1870
- cellWidth="auto"
1871
- style={
1872
- {
1873
- display: "block",
1874
- overflow: "hidden",
1875
- width: "100%",
1876
- minWidth: 0,
1877
- } as any
1878
- }
1879
- {...({
1880
- colSpan:
1881
- table.getVisibleLeafColumns().length +
1882
- extraColumnsBefore +
1883
- extraColumnsAfter,
1884
- } as any)}
1885
- >
1886
- <DataTableVirtualized
1887
- virtualItems={virtualItems}
1888
- totalSize={totalSize}
1889
- bodyScrollRef={bodyScrollRef}
1890
- virtualizationHeight={virtualizationHeight}
1891
- tableRows={displayRows}
1892
- headerGroups={headerGroups}
1893
- showRowNumbers={showRowNumbers}
1894
- enableRowExpansion={enableRowExpansion}
1895
- showDeleteRow={showDeleteRow}
1896
- readOnly={readOnly}
1897
- enableKeyboardNavigation={enableKeyboardNavigation}
1898
- keyboardNav={keyboardNav}
1899
- getColSizeProps={getColSizeProps}
1900
- renderRowContent={renderRowContent}
1901
- extraColumnsBefore={extraColumnsBefore}
1902
- extraColumnsAfter={extraColumnsAfter}
1903
- table={table}
1904
- hasInfiniteTail={hasInfiniteTail}
1905
- rowHeightPx={rowHeightPx}
1906
- tableZebraOn={tableZebraOn}
1907
- {...(rowPressActive ? { getRowPressProps } : {})}
1908
- />
1909
- </Table.Cell>
1910
- </Table.Row>
1911
- ) : (
1912
- <>
1913
- {displayRows.map((row: any, index: number) => {
1914
- rowCounter.current++;
1915
- const isLastRow = index === displayRows.length - 1;
1916
-
1917
- // Grouped row: render a single header cell spanning all columns
1918
- // with expand toggle, group label, and item count.
1919
- if (enableGrouping && row.getIsGrouped?.()) {
1920
- const colSpan =
1921
- table.getVisibleLeafColumns().length +
1922
- extraColumnsBefore +
1923
- extraColumnsAfter;
1924
- const indent = (row.depth ?? 0) * chrome.indent;
1925
- return (
1905
+ </Table.Cell>
1906
+ </Table.Row>
1907
+ ) : (
1908
+ <>
1909
+ {displayRows.map((row: any, index: number) => {
1910
+ rowCounter.current++;
1911
+ const isLastRow = index === displayRows.length - 1;
1912
+
1913
+ // Grouped row: render a single header cell spanning all columns
1914
+ // with expand toggle, group label, and item count.
1915
+ if (enableGrouping && row.getIsGrouped?.()) {
1916
+ const colSpan =
1917
+ table.getVisibleLeafColumns().length +
1918
+ extraColumnsBefore +
1919
+ extraColumnsAfter;
1920
+ const indent = (row.depth ?? 0) * chrome.indent;
1921
+ return (
1922
+ <Table.Row
1923
+ key={row.id}
1924
+ backgroundColor="$color3"
1925
+ flexShrink={0}
1926
+ aria-rowindex={rowCounter.current}
1927
+ >
1928
+ <Table.Cell {...({ colSpan } as any)}>
1929
+ <View
1930
+ flexDirection="row"
1931
+ alignItems="center"
1932
+ gap="$2"
1933
+ paddingInlineStart={indent}
1934
+ cursor="pointer"
1935
+ onPress={() => row.toggleExpanded()}
1936
+ // Keyboard/AT contract: expandable group
1937
+ // header is a toggle button (Enter/Space).
1938
+ role="button"
1939
+ tabIndex={0}
1940
+ aria-expanded={row.getIsExpanded()}
1941
+ {...({
1942
+ onKeyDown: (e: React.KeyboardEvent) => {
1943
+ if (e.key === "Enter" || e.key === " ") {
1944
+ e.preventDefault();
1945
+ row.toggleExpanded();
1946
+ }
1947
+ },
1948
+ } as any)}
1949
+ >
1950
+ <Text fontFamily="$mono" fontSize="$3">
1951
+ {row.getIsExpanded() ? "▼" : "▶"}
1952
+ </Text>
1953
+ <SizableText
1954
+ fontFamily={knobProps.heading.fontFamily}
1955
+ size="$4"
1956
+ >
1957
+ {String(row.groupingValue ?? "—")}
1958
+ </SizableText>
1959
+ <Text color="$placeholderColor" fontSize="$2">
1960
+ ({row.subRows?.length ?? 0})
1961
+ </Text>
1962
+ </View>
1963
+ </Table.Cell>
1964
+ </Table.Row>
1965
+ );
1966
+ }
1967
+
1968
+ const mainRow = (
1926
1969
  <Table.Row
1927
- key={row.id}
1928
- backgroundColor="$color3"
1970
+ {...(tableRowStateProps({
1971
+ selected: Boolean(enableRowSelection && row.getIsSelected?.()),
1972
+ keyboardFocused: false,
1973
+ zebraOn: tableZebraOn,
1974
+ index,
1975
+ pressable: rowPressActive,
1976
+ }) as any)}
1977
+ {...({ animation: "quick" } as any)}
1929
1978
  flexShrink={0}
1979
+ rowLocation={
1980
+ rowCounter.current === 0
1981
+ ? "first"
1982
+ : rowCounter.current === allRowsLength - 1
1983
+ ? "last"
1984
+ : "middle"
1985
+ }
1986
+ key={`${row.id}-${index}`}
1930
1987
  aria-rowindex={rowCounter.current}
1988
+ aria-label={withInterp(t("Row {{row}}", { row: index + 1 }), {
1989
+ row: index + 1,
1990
+ })}
1991
+ tabIndex={-1}
1992
+ {...({
1993
+ "data-table-zebra": tableZebraOn
1994
+ ? index % 2 === 0
1995
+ ? "even"
1996
+ : "odd"
1997
+ : "off",
1998
+ } as any)}
1999
+ {...(getRowPressProps(row, index) as any)}
2000
+ {...(rowIntentProps(row.original) as any)}
1931
2001
  >
1932
- <Table.Cell {...({ colSpan } as any)}>
1933
- <View
1934
- flexDirection="row"
1935
- alignItems="center"
1936
- gap="$2"
1937
- paddingInlineStart={indent}
1938
- cursor="pointer"
1939
- onPress={() => row.toggleExpanded()}
1940
- // Keyboard/AT contract: expandable group
1941
- // header is a toggle button (Enter/Space).
1942
- role="button"
1943
- tabIndex={0}
1944
- aria-expanded={row.getIsExpanded()}
2002
+ {renderRowContent(row, index, isLastRow)}
2003
+ </Table.Row>
2004
+ );
2005
+
2006
+ const subRow =
2007
+ enableRowExpansion &&
2008
+ renderSubComponent &&
2009
+ row.getIsExpanded() &&
2010
+ !row.subRows?.length ? (
2011
+ <Table.Row key={`${row.id}-sub`} backgroundColor="$color2">
2012
+ <Table.Cell
1945
2013
  {...({
1946
- onKeyDown: (e: React.KeyboardEvent) => {
1947
- if (e.key === "Enter" || e.key === " ") {
1948
- e.preventDefault();
1949
- row.toggleExpanded();
1950
- }
1951
- },
2014
+ colSpan:
2015
+ table.getVisibleLeafColumns().length +
2016
+ extraColumnsBefore +
2017
+ extraColumnsAfter,
1952
2018
  } as any)}
1953
2019
  >
1954
- <Text fontFamily="$mono" fontSize="$3">
1955
- {row.getIsExpanded() ? "▼" : "▶"}
1956
- </Text>
1957
- <Text fontWeight="600">{String(row.groupingValue ?? "—")}</Text>
1958
- <Text color="$placeholderColor" fontSize="$2">
1959
- ({row.subRows?.length ?? 0})
1960
- </Text>
1961
- </View>
1962
- </Table.Cell>
1963
- </Table.Row>
1964
- );
1965
- }
2020
+ {renderSubComponent(row)}
2021
+ </Table.Cell>
2022
+ </Table.Row>
2023
+ ) : null;
1966
2024
 
1967
- const mainRow = (
2025
+ return (
2026
+ <React.Fragment key={row.id}>
2027
+ {mainRow}
2028
+ {subRow}
2029
+ </React.Fragment>
2030
+ );
2031
+ })}
2032
+ {/* Filler row — fills remaining space with background */}
2033
+ {isFlexLayout && (
1968
2034
  <Table.Row
1969
- {...(tableRowStateProps({
1970
- selected: Boolean(enableRowSelection && row.getIsSelected?.()),
1971
- keyboardFocused: false,
1972
- zebraOn: tableZebraOn,
1973
- index,
1974
- pressable: rowPressActive,
1975
- }) as any)}
1976
- {...({ animation: "quick" } as any)}
1977
- flexShrink={0}
1978
- rowLocation={
1979
- rowCounter.current === 0
2035
+ key="filler-row"
2036
+ aria-hidden={true}
2037
+ backgroundColor="$color1"
2038
+ flex={1}
2039
+ flexShrink={1}
2040
+ flexGrow={1}
2041
+ flexBasis={0}
2042
+ minHeight={0}
2043
+ >
2044
+ {enableRowSelection && (
2045
+ <Table.Cell
2046
+ cellWidth={selectionColWidth}
2047
+ cellLocation="first"
2048
+ padding={0}
2049
+ minHeight={0}
2050
+ />
2051
+ )}
2052
+ {showRowNumbers && (
2053
+ <Table.Cell
2054
+ cellWidth={chrome.rowNumberCol}
2055
+ cellLocation={enableRowSelection ? "middle" : "first"}
2056
+ padding={0}
2057
+ minHeight={0}
2058
+ />
2059
+ )}
2060
+ {enableRowExpansion && (
2061
+ <Table.Cell
2062
+ cellWidth={chrome.expandCol}
2063
+ cellLocation={
2064
+ enableRowSelection || showRowNumbers ? "middle" : "first"
2065
+ }
2066
+ padding={0}
2067
+ minHeight={0}
2068
+ />
2069
+ )}
2070
+ {headerGroups[0]?.headers.map((header: any, headerIndex: number) => {
2071
+ const isFirstDataCell =
2072
+ headerIndex === 0 &&
2073
+ !enableRowSelection &&
2074
+ !showRowNumbers &&
2075
+ !enableRowExpansion;
2076
+ const isLastDataCell =
2077
+ headerIndex === headerGroups[0].headers.length - 1 &&
2078
+ !(showDeleteRow && !readOnly);
2079
+ const cellLoc = isFirstDataCell
1980
2080
  ? "first"
1981
- : rowCounter.current === allRowsLength - 1
2081
+ : isLastDataCell
1982
2082
  ? "last"
1983
- : "middle"
1984
- }
1985
- key={`${row.id}-${index}`}
1986
- aria-rowindex={rowCounter.current}
1987
- aria-label={withInterp(t("Row {{row}}", { row: index + 1 }), {
1988
- row: index + 1,
2083
+ : "middle";
2084
+ return (
2085
+ <Table.Cell
2086
+ key={header.id}
2087
+ {...cellFlexProps}
2088
+ {...getColSizeProps(header.column)}
2089
+ cellLocation={cellLoc}
2090
+ padding={0}
2091
+ minHeight={0}
2092
+ />
2093
+ );
1989
2094
  })}
1990
- tabIndex={-1}
1991
- {...({
1992
- "data-table-zebra": tableZebraOn
1993
- ? index % 2 === 0
1994
- ? "even"
1995
- : "odd"
1996
- : "off",
1997
- } as any)}
1998
- {...(getRowPressProps(row, index) as any)}
1999
- {...(rowIntentProps(row.original) as any)}
2000
- >
2001
- {renderRowContent(row, index, isLastRow)}
2002
- </Table.Row>
2003
- );
2004
-
2005
- const subRow =
2006
- enableRowExpansion &&
2007
- renderSubComponent &&
2008
- row.getIsExpanded() &&
2009
- !row.subRows?.length ? (
2010
- <Table.Row key={`${row.id}-sub`} backgroundColor="$color2">
2095
+ {showDeleteRow && !readOnly && (
2011
2096
  <Table.Cell
2012
- {...({
2013
- colSpan:
2014
- table.getVisibleLeafColumns().length +
2015
- extraColumnsBefore +
2016
- extraColumnsAfter,
2017
- } as any)}
2018
- >
2019
- {renderSubComponent(row)}
2020
- </Table.Cell>
2021
- </Table.Row>
2022
- ) : null;
2023
-
2024
- return (
2025
- <React.Fragment key={row.id}>
2026
- {mainRow}
2027
- {subRow}
2028
- </React.Fragment>
2029
- );
2030
- })}
2031
- {/* Filler row — fills remaining space with background */}
2032
- {isFlexLayout && (
2033
- <Table.Row
2034
- key="filler-row"
2035
- aria-hidden={true}
2036
- backgroundColor="$color1"
2037
- flex={1}
2038
- flexShrink={1}
2039
- flexGrow={1}
2040
- flexBasis={0}
2041
- minHeight={0}
2042
- >
2097
+ cellWidth={chrome.deleteCol}
2098
+ cellLocation="last"
2099
+ padding={0}
2100
+ minHeight={0}
2101
+ />
2102
+ )}
2103
+ </Table.Row>
2104
+ )}
2105
+ </>
2106
+ )}
2107
+ {/* DF-12 / Axiom 6: clipped-viewport affordance — rows are
2108
+ cut off below the fold, so the frame says so with a
2109
+ bottom fade that clears once the last row is reached.
2110
+ Sticky inside the scroll container; zero layout cost
2111
+ (a zero-height row whose cell paints the fade upward
2112
+ over the last visible row). Rendered as a Table.Row
2113
+ and a <td>: a <div> is not a valid child of the real
2114
+ <tbody> or <tr> (SSR parsers foster-parent it out of
2115
+ the table). Only reachable in the flex displayMode
2116
+ (bodyClipped needs a scrollable body), where the row
2117
+ renders display:flex like the old View. */}
2118
+ {isWeb && bodyClipped && (
2119
+ <Table.Row
2120
+ aria-hidden={true}
2121
+ role="presentation"
2122
+ position={"sticky" as any}
2123
+ bottom={0}
2124
+ height={0}
2125
+ flexShrink={0}
2126
+ zIndex={2}
2127
+ pointerEvents="none"
2128
+ {...({ "data-table-clip-affordance": "true" } as any)}
2129
+ >
2130
+ <View
2131
+ {...({ render: "td" } as Record<string, unknown>)}
2132
+ position="absolute"
2133
+ left={0}
2134
+ right={0}
2135
+ bottom={0}
2136
+ height={28}
2137
+ style={{
2138
+ background:
2139
+ "linear-gradient(to bottom, rgba(0,0,0,0), var(--background))",
2140
+ }}
2141
+ />
2142
+ </Table.Row>
2143
+ )}
2144
+ </Table.Body>
2145
+
2146
+ {/* Table Footer */}
2147
+ {hasFooter && (
2148
+ <Table.Foot>
2149
+ {footerGroups.map((footerGroup: any) => (
2150
+ <Table.Row key={footerGroup.id}>
2043
2151
  {enableRowSelection && (
2044
2152
  <Table.Cell
2045
2153
  cellWidth={selectionColWidth}
2154
+ cellHeight={cellHeight as any}
2046
2155
  cellLocation="first"
2047
- padding={0}
2048
- minHeight={0}
2049
2156
  />
2050
2157
  )}
2051
2158
  {showRowNumbers && (
2052
2159
  <Table.Cell
2053
2160
  cellWidth={chrome.rowNumberCol}
2161
+ cellHeight={cellHeight as any}
2054
2162
  cellLocation={enableRowSelection ? "middle" : "first"}
2055
- padding={0}
2056
- minHeight={0}
2057
2163
  />
2058
2164
  )}
2059
2165
  {enableRowExpansion && (
2060
2166
  <Table.Cell
2061
2167
  cellWidth={chrome.expandCol}
2168
+ cellHeight={cellHeight as any}
2062
2169
  cellLocation={
2063
2170
  enableRowSelection || showRowNumbers ? "middle" : "first"
2064
2171
  }
2065
- padding={0}
2066
- minHeight={0}
2067
2172
  />
2068
2173
  )}
2069
- {headerGroups[0]?.headers.map((header: any, headerIndex: number) => {
2070
- const isFirstDataCell =
2071
- headerIndex === 0 &&
2072
- !enableRowSelection &&
2073
- !showRowNumbers &&
2074
- !enableRowExpansion;
2075
- const isLastDataCell =
2076
- headerIndex === headerGroups[0].headers.length - 1 &&
2077
- !(showDeleteRow && !readOnly);
2078
- const cellLoc = isFirstDataCell
2079
- ? "first"
2080
- : isLastDataCell
2081
- ? "last"
2082
- : "middle";
2174
+ {footerGroup.headers.map((header: any) => {
2175
+ const stickyStyle = getStickyStyle(header.column.id);
2176
+ const columnAlign = resolveColumnAlign({
2177
+ ...(header.column.columnDef as DataTableColumn),
2178
+ id: header.column.id,
2179
+ });
2083
2180
  return (
2084
2181
  <Table.Cell
2085
2182
  key={header.id}
2086
2183
  {...cellFlexProps}
2087
2184
  {...getColSizeProps(header.column)}
2088
- cellLocation={cellLoc}
2089
- padding={0}
2090
- minHeight={0}
2091
- />
2185
+ {...(isWeb && stickyStyle
2186
+ ? {
2187
+ style: {
2188
+ position: "sticky",
2189
+ ...("insetInlineStart" in stickyStyle && {
2190
+ insetInlineStart: stickyStyle.insetInlineStart,
2191
+ }),
2192
+ ...("insetInlineEnd" in stickyStyle && {
2193
+ insetInlineEnd: stickyStyle.insetInlineEnd,
2194
+ }),
2195
+ zIndex: 2,
2196
+ backgroundColor: "var(--color2)",
2197
+ } as React.CSSProperties,
2198
+ }
2199
+ : {})}
2200
+ justifyContent={alignToFlex(columnAlign)}
2201
+ data-align={columnAlign}
2202
+ >
2203
+ {header.isPlaceholder ? null : (
2204
+ <View
2205
+ width="100%"
2206
+ minWidth={0}
2207
+ flexDirection="row"
2208
+ alignItems="center"
2209
+ justifyContent={alignToFlex(columnAlign)}
2210
+ data-cell-align={columnAlign}
2211
+ style={isWeb ? { textAlign: columnAlign } : undefined}
2212
+ >
2213
+ {flexRender(
2214
+ header.column.columnDef.footer,
2215
+ header.getContext(),
2216
+ )}
2217
+ </View>
2218
+ )}
2219
+ </Table.Cell>
2092
2220
  );
2093
2221
  })}
2094
2222
  {showDeleteRow && !readOnly && (
2095
2223
  <Table.Cell
2096
2224
  cellWidth={chrome.deleteCol}
2225
+ cellHeight={cellHeight as any}
2097
2226
  cellLocation="last"
2098
- padding={0}
2099
- minHeight={0}
2100
2227
  />
2101
2228
  )}
2102
2229
  </Table.Row>
2103
- )}
2104
- </>
2230
+ ))}
2231
+ </Table.Foot>
2105
2232
  )}
2106
- {/* DF-12 / Axiom 6: clipped-viewport affordance — rows are
2107
- cut off below the fold, so the frame says so with a
2108
- bottom fade that clears once the last row is reached.
2109
- Sticky inside the scroll container; zero layout cost
2110
- (a zero-height row whose cell paints the fade upward
2111
- over the last visible row). Rendered as a Table.Row
2112
- and a <td>: a <div> is not a valid child of the real
2113
- <tbody> or <tr> (SSR parsers foster-parent it out of
2114
- the table). Only reachable in the flex displayMode
2115
- (bodyClipped needs a scrollable body), where the row
2116
- renders display:flex like the old View. */}
2117
- {isWeb && bodyClipped && (
2118
- <Table.Row
2119
- aria-hidden={true}
2120
- role="presentation"
2121
- position={"sticky" as any}
2122
- bottom={0}
2123
- height={0}
2124
- flexShrink={0}
2125
- zIndex={2}
2126
- pointerEvents="none"
2127
- {...({ "data-table-clip-affordance": "true" } as any)}
2128
- >
2129
- <View
2130
- {...({ render: "td" } as Record<string, unknown>)}
2131
- position="absolute"
2132
- left={0}
2133
- right={0}
2134
- bottom={0}
2135
- height={28}
2136
- style={{
2137
- background:
2138
- "linear-gradient(to bottom, rgba(0,0,0,0), var(--background))",
2139
- }}
2140
- />
2141
- </Table.Row>
2142
- )}
2143
- </Table.Body>
2144
-
2145
- {/* Table Footer */}
2146
- {hasFooter && (
2147
- <Table.Foot>
2148
- {footerGroups.map((footerGroup: any) => (
2149
- <Table.Row key={footerGroup.id}>
2150
- {enableRowSelection && (
2151
- <Table.Cell
2152
- cellWidth={selectionColWidth}
2153
- cellHeight={cellHeight as any}
2154
- cellLocation="first"
2155
- />
2156
- )}
2157
- {showRowNumbers && (
2158
- <Table.Cell
2159
- cellWidth={chrome.rowNumberCol}
2160
- cellHeight={cellHeight as any}
2161
- cellLocation={enableRowSelection ? "middle" : "first"}
2162
- />
2163
- )}
2164
- {enableRowExpansion && (
2165
- <Table.Cell
2166
- cellWidth={chrome.expandCol}
2167
- cellHeight={cellHeight as any}
2168
- cellLocation={
2169
- enableRowSelection || showRowNumbers ? "middle" : "first"
2170
- }
2171
- />
2172
- )}
2173
- {footerGroup.headers.map((header: any) => {
2174
- const stickyStyle = getStickyStyle(header.column.id);
2175
- const columnAlign = resolveColumnAlign({
2176
- ...(header.column.columnDef as DataTableColumn),
2177
- id: header.column.id,
2178
- });
2179
- return (
2180
- <Table.Cell
2181
- key={header.id}
2182
- {...cellFlexProps}
2183
- {...getColSizeProps(header.column)}
2184
- {...(isWeb && stickyStyle
2185
- ? {
2186
- style: {
2187
- position: "sticky",
2188
- ...("insetInlineStart" in stickyStyle && {
2189
- insetInlineStart: stickyStyle.insetInlineStart,
2190
- }),
2191
- ...("insetInlineEnd" in stickyStyle && {
2192
- insetInlineEnd: stickyStyle.insetInlineEnd,
2193
- }),
2194
- zIndex: 2,
2195
- backgroundColor: "var(--color2)",
2196
- } as React.CSSProperties,
2197
- }
2198
- : {})}
2199
- justifyContent={alignToFlex(columnAlign)}
2200
- data-align={columnAlign}
2201
- >
2202
- {header.isPlaceholder ? null : (
2203
- <View
2204
- width="100%"
2205
- minWidth={0}
2206
- flexDirection="row"
2207
- alignItems="center"
2208
- justifyContent={alignToFlex(columnAlign)}
2209
- data-cell-align={columnAlign}
2210
- style={isWeb ? { textAlign: columnAlign } : undefined}
2211
- >
2212
- {flexRender(
2213
- header.column.columnDef.footer,
2214
- header.getContext(),
2215
- )}
2216
- </View>
2217
- )}
2218
- </Table.Cell>
2219
- );
2220
- })}
2221
- {showDeleteRow && !readOnly && (
2222
- <Table.Cell
2223
- cellWidth={chrome.deleteCol}
2224
- cellHeight={cellHeight as any}
2225
- cellLocation="last"
2226
- />
2227
- )}
2228
- </Table.Row>
2229
- ))}
2230
- </Table.Foot>
2231
- )}
2232
- </Table>
2233
- </View>
2234
- )}
2235
-
2236
- {infinite ? (
2237
- <DataTableInfiniteTail
2238
- infinite={infinite}
2239
- visibleCount={tableRows.length}
2240
- showAppendSkeleton={!isVirtualized}
2241
- rowHeightPx={rowHeightPx}
2242
- fontSize={knobProps.sizeToken}
2243
- gapProps={knobProps.gap}
2244
- sentinel={
2245
- !isVirtualized && !infinite.exhausted && !infinite.appendError && isWeb ? (
2246
- <View
2247
- // @ts-ignore web ref for IntersectionObserver
2248
- ref={sentinelRef as any}
2249
- height={1}
2250
- width="100%"
2251
- aria-hidden
2252
- {...({ "data-testid": "infinite-sentinel" } as any)}
2253
- />
2254
- ) : null
2255
- }
2256
- />
2257
- ) : null}
2258
-
2259
- {enableRowSelection && bulkBarPlacement === "bottom" ? (
2260
- <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
2261
- <DataTableBulkActions
2262
- actions={resolvedBulkActions}
2263
- maxVisibleActions={5}
2264
- showSelectionCount
2265
- placement="bottom"
2233
+ </Table>
2234
+ </View>
2235
+ )}
2236
+
2237
+ {infinite ? (
2238
+ <DataTableInfiniteTail
2239
+ infinite={infinite}
2240
+ visibleCount={tableRows.length}
2241
+ showAppendSkeleton={!isVirtualized}
2242
+ rowHeightPx={rowHeightPx}
2243
+ fontSize={knobProps.sizeToken}
2244
+ gapProps={knobProps.gap}
2245
+ sentinel={
2246
+ !isVirtualized && !infinite.exhausted && !infinite.appendError && isWeb ? (
2247
+ <View
2248
+ // @ts-ignore web ref for IntersectionObserver
2249
+ ref={sentinelRef as any}
2250
+ height={1}
2251
+ width="100%"
2252
+ aria-hidden
2253
+ {...({ "data-testid": "infinite-sentinel" } as any)}
2254
+ />
2255
+ ) : null
2256
+ }
2266
2257
  />
2267
- </View>
2268
- ) : null}
2269
-
2270
- {/* Add Row Button */}
2271
- {showAddRow && !readOnly && (
2272
- <View>
2273
- <Button
2274
- icon={PlusIcon}
2275
- disabled={disabled || (maxRows !== undefined && tableData.length >= maxRows)}
2276
- onPress={effectiveHandleAddRow}
2277
- aria-label={t("Add Row")}
2278
- >
2279
- {t("Add Row")}
2280
- </Button>
2281
- </View>
2282
- )}
2258
+ ) : null}
2259
+
2260
+ {enableRowSelection && bulkBarPlacement === "bottom" ? (
2261
+ <View width="100%" {...(disabled ? disabledState.chromeKnobProps : {})}>
2262
+ <DataTableBulkActions
2263
+ actions={resolvedBulkActions}
2264
+ maxVisibleActions={5}
2265
+ showSelectionCount
2266
+ placement="bottom"
2267
+ />
2268
+ </View>
2269
+ ) : null}
2270
+
2271
+ {/* Add Row Button */}
2272
+ {showAddRow && !readOnly && (
2273
+ <View>
2274
+ <Button
2275
+ icon={PlusIcon}
2276
+ disabled={disabled || (maxRows !== undefined && tableData.length >= maxRows)}
2277
+ onPress={effectiveHandleAddRow}
2278
+ aria-label={t("Add Row")}
2279
+ >
2280
+ {t("Add Row")}
2281
+ </Button>
2282
+ </View>
2283
+ )}
2284
+ </Surface>
2283
2285
 
2284
2286
  {/* Pagination footer (pages mode only; infinite replaces it with the tail status) */}
2285
2287
  {enablePagination && !infinite && (