@lucasbernardosn/react-table 0.0.0-stage → 0.1.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 (267) hide show
  1. package/LICENSE +21 -0
  2. package/dist/_virtual/_rolldown/runtime.js +13 -0
  3. package/dist/components/column-menu/column-menu-check.d.ts +8 -0
  4. package/dist/components/column-menu/column-menu-check.d.ts.map +1 -0
  5. package/dist/components/column-menu/column-menu-check.js +17 -0
  6. package/dist/components/column-menu/column-menu-check.js.map +1 -0
  7. package/dist/components/column-menu/column-menu-hide-item.d.ts +23 -0
  8. package/dist/components/column-menu/column-menu-hide-item.d.ts.map +1 -0
  9. package/dist/components/column-menu/column-menu-hide-item.js +28 -0
  10. package/dist/components/column-menu/column-menu-hide-item.js.map +1 -0
  11. package/dist/components/column-menu/column-menu-labels.d.ts +21 -0
  12. package/dist/components/column-menu/column-menu-labels.d.ts.map +1 -0
  13. package/dist/components/column-menu/column-menu-labels.js +14 -0
  14. package/dist/components/column-menu/column-menu-labels.js.map +1 -0
  15. package/dist/components/column-menu/column-menu-pin-items.d.ts +25 -0
  16. package/dist/components/column-menu/column-menu-pin-items.d.ts.map +1 -0
  17. package/dist/components/column-menu/column-menu-pin-items.js +65 -0
  18. package/dist/components/column-menu/column-menu-pin-items.js.map +1 -0
  19. package/dist/components/column-menu/column-menu-popup.d.ts +39 -0
  20. package/dist/components/column-menu/column-menu-popup.d.ts.map +1 -0
  21. package/dist/components/column-menu/column-menu-popup.js +66 -0
  22. package/dist/components/column-menu/column-menu-popup.js.map +1 -0
  23. package/dist/components/column-menu/column-menu-root.d.ts +34 -0
  24. package/dist/components/column-menu/column-menu-root.d.ts.map +1 -0
  25. package/dist/components/column-menu/column-menu-root.js +36 -0
  26. package/dist/components/column-menu/column-menu-root.js.map +1 -0
  27. package/dist/components/column-menu/column-menu-sort-items.d.ts +29 -0
  28. package/dist/components/column-menu/column-menu-sort-items.d.ts.map +1 -0
  29. package/dist/components/column-menu/column-menu-sort-items.js +61 -0
  30. package/dist/components/column-menu/column-menu-sort-items.js.map +1 -0
  31. package/dist/components/column-menu/column-menu-trigger.d.ts +23 -0
  32. package/dist/components/column-menu/column-menu-trigger.d.ts.map +1 -0
  33. package/dist/components/column-menu/column-menu-trigger.js +38 -0
  34. package/dist/components/column-menu/column-menu-trigger.js.map +1 -0
  35. package/dist/components/column-menu/index.d.ts +2 -0
  36. package/dist/components/column-menu/index.js +2 -0
  37. package/dist/components/column-menu/index.parts.d.ts +13 -0
  38. package/dist/components/column-menu/index.parts.d.ts.map +1 -0
  39. package/dist/components/column-menu/index.parts.js +20 -0
  40. package/dist/components/column-menu/index.parts.js.map +1 -0
  41. package/dist/components/columns-panel/columns-panel-item.d.ts +31 -0
  42. package/dist/components/columns-panel/columns-panel-item.d.ts.map +1 -0
  43. package/dist/components/columns-panel/columns-panel-item.js +92 -0
  44. package/dist/components/columns-panel/columns-panel-item.js.map +1 -0
  45. package/dist/components/columns-panel/columns-panel-root.d.ts +51 -0
  46. package/dist/components/columns-panel/columns-panel-root.d.ts.map +1 -0
  47. package/dist/components/columns-panel/columns-panel-root.js +134 -0
  48. package/dist/components/columns-panel/columns-panel-root.js.map +1 -0
  49. package/dist/components/columns-panel/get-columns-panel-column-order.d.ts +16 -0
  50. package/dist/components/columns-panel/get-columns-panel-column-order.d.ts.map +1 -0
  51. package/dist/components/columns-panel/get-columns-panel-column-order.js +24 -0
  52. package/dist/components/columns-panel/get-columns-panel-column-order.js.map +1 -0
  53. package/dist/components/columns-panel/index.d.ts +2 -0
  54. package/dist/components/columns-panel/index.js +2 -0
  55. package/dist/components/columns-panel/index.parts.d.ts +8 -0
  56. package/dist/components/columns-panel/index.parts.d.ts.map +1 -0
  57. package/dist/components/columns-panel/index.parts.js +12 -0
  58. package/dist/components/columns-panel/index.parts.js.map +1 -0
  59. package/dist/components/data-table/body/data-table-body.d.ts +58 -0
  60. package/dist/components/data-table/body/data-table-body.d.ts.map +1 -0
  61. package/dist/components/data-table/body/data-table-body.js +99 -0
  62. package/dist/components/data-table/body/data-table-body.js.map +1 -0
  63. package/dist/components/data-table/body/data-table-cell.d.ts +26 -0
  64. package/dist/components/data-table/body/data-table-cell.d.ts.map +1 -0
  65. package/dist/components/data-table/body/data-table-cell.js +80 -0
  66. package/dist/components/data-table/body/data-table-cell.js.map +1 -0
  67. package/dist/components/data-table/body/data-table-empty.d.ts +38 -0
  68. package/dist/components/data-table/body/data-table-empty.d.ts.map +1 -0
  69. package/dist/components/data-table/body/data-table-empty.js +71 -0
  70. package/dist/components/data-table/body/data-table-empty.js.map +1 -0
  71. package/dist/components/data-table/body/data-table-row-focus.d.ts +32 -0
  72. package/dist/components/data-table/body/data-table-row-focus.d.ts.map +1 -0
  73. package/dist/components/data-table/body/data-table-row-focus.js +58 -0
  74. package/dist/components/data-table/body/data-table-row-focus.js.map +1 -0
  75. package/dist/components/data-table/body/data-table-row.d.ts +67 -0
  76. package/dist/components/data-table/body/data-table-row.d.ts.map +1 -0
  77. package/dist/components/data-table/body/data-table-row.js +150 -0
  78. package/dist/components/data-table/body/data-table-row.js.map +1 -0
  79. package/dist/components/data-table/body/use-data-table-row-focus-recovery.d.ts +19 -0
  80. package/dist/components/data-table/body/use-data-table-row-focus-recovery.d.ts.map +1 -0
  81. package/dist/components/data-table/body/use-data-table-row-focus-recovery.js +64 -0
  82. package/dist/components/data-table/body/use-data-table-row-focus-recovery.js.map +1 -0
  83. package/dist/components/data-table/header/data-table-header-button.d.ts +25 -0
  84. package/dist/components/data-table/header/data-table-header-button.d.ts.map +1 -0
  85. package/dist/components/data-table/header/data-table-header-button.js +57 -0
  86. package/dist/components/data-table/header/data-table-header-button.js.map +1 -0
  87. package/dist/components/data-table/header/data-table-header-cell.d.ts +34 -0
  88. package/dist/components/data-table/header/data-table-header-cell.d.ts.map +1 -0
  89. package/dist/components/data-table/header/data-table-header-cell.js +97 -0
  90. package/dist/components/data-table/header/data-table-header-cell.js.map +1 -0
  91. package/dist/components/data-table/header/data-table-header-content.d.ts +21 -0
  92. package/dist/components/data-table/header/data-table-header-content.d.ts.map +1 -0
  93. package/dist/components/data-table/header/data-table-header-content.js +37 -0
  94. package/dist/components/data-table/header/data-table-header-content.js.map +1 -0
  95. package/dist/components/data-table/header/data-table-header-row.d.ts +15 -0
  96. package/dist/components/data-table/header/data-table-header-row.d.ts.map +1 -0
  97. package/dist/components/data-table/header/data-table-header-row.js +28 -0
  98. package/dist/components/data-table/header/data-table-header-row.js.map +1 -0
  99. package/dist/components/data-table/header/data-table-header.d.ts +46 -0
  100. package/dist/components/data-table/header/data-table-header.d.ts.map +1 -0
  101. package/dist/components/data-table/header/data-table-header.js +80 -0
  102. package/dist/components/data-table/header/data-table-header.js.map +1 -0
  103. package/dist/components/data-table/index.d.ts +2 -0
  104. package/dist/components/data-table/index.js +2 -0
  105. package/dist/components/data-table/index.parts.d.ts +32 -0
  106. package/dist/components/data-table/index.parts.d.ts.map +1 -0
  107. package/dist/components/data-table/index.parts.js +60 -0
  108. package/dist/components/data-table/index.parts.js.map +1 -0
  109. package/dist/components/data-table/loading/get-data-table-loading-without-rows.d.ts +16 -0
  110. package/dist/components/data-table/loading/get-data-table-loading-without-rows.d.ts.map +1 -0
  111. package/dist/components/data-table/loading/get-data-table-loading-without-rows.js +18 -0
  112. package/dist/components/data-table/loading/get-data-table-loading-without-rows.js.map +1 -0
  113. package/dist/components/data-table/loading/use-data-table-loading-inert.d.ts +16 -0
  114. package/dist/components/data-table/loading/use-data-table-loading-inert.d.ts.map +1 -0
  115. package/dist/components/data-table/loading/use-data-table-loading-inert.js +54 -0
  116. package/dist/components/data-table/loading/use-data-table-loading-inert.js.map +1 -0
  117. package/dist/components/data-table/loading/use-data-table-loading.d.ts +13 -0
  118. package/dist/components/data-table/loading/use-data-table-loading.d.ts.map +1 -0
  119. package/dist/components/data-table/loading/use-data-table-loading.js +40 -0
  120. package/dist/components/data-table/loading/use-data-table-loading.js.map +1 -0
  121. package/dist/components/data-table/pagination/data-table-page-button.d.ts +45 -0
  122. package/dist/components/data-table/pagination/data-table-page-button.d.ts.map +1 -0
  123. package/dist/components/data-table/pagination/data-table-page-button.js +67 -0
  124. package/dist/components/data-table/pagination/data-table-page-button.js.map +1 -0
  125. package/dist/components/data-table/pagination/data-table-page-size-select.d.ts +47 -0
  126. package/dist/components/data-table/pagination/data-table-page-size-select.d.ts.map +1 -0
  127. package/dist/components/data-table/pagination/data-table-page-size-select.js +68 -0
  128. package/dist/components/data-table/pagination/data-table-page-size-select.js.map +1 -0
  129. package/dist/components/data-table/pagination/data-table-page-status.d.ts +43 -0
  130. package/dist/components/data-table/pagination/data-table-page-status.d.ts.map +1 -0
  131. package/dist/components/data-table/pagination/data-table-page-status.js +48 -0
  132. package/dist/components/data-table/pagination/data-table-page-status.js.map +1 -0
  133. package/dist/components/data-table/pagination/data-table-pagination.d.ts +38 -0
  134. package/dist/components/data-table/pagination/data-table-pagination.d.ts.map +1 -0
  135. package/dist/components/data-table/pagination/data-table-pagination.js +87 -0
  136. package/dist/components/data-table/pagination/data-table-pagination.js.map +1 -0
  137. package/dist/components/data-table/pagination/data-table-row-range.d.ts +49 -0
  138. package/dist/components/data-table/pagination/data-table-row-range.d.ts.map +1 -0
  139. package/dist/components/data-table/pagination/data-table-row-range.js +63 -0
  140. package/dist/components/data-table/pagination/data-table-row-range.js.map +1 -0
  141. package/dist/components/data-table/pagination/data-table-selected-count.d.ts +37 -0
  142. package/dist/components/data-table/pagination/data-table-selected-count.d.ts.map +1 -0
  143. package/dist/components/data-table/pagination/data-table-selected-count.js +44 -0
  144. package/dist/components/data-table/pagination/data-table-selected-count.js.map +1 -0
  145. package/dist/components/data-table/pagination/use-data-table-page-scroll-reset.d.ts +15 -0
  146. package/dist/components/data-table/pagination/use-data-table-page-scroll-reset.d.ts.map +1 -0
  147. package/dist/components/data-table/pagination/use-data-table-page-scroll-reset.js +38 -0
  148. package/dist/components/data-table/pagination/use-data-table-page-scroll-reset.js.map +1 -0
  149. package/dist/components/data-table/resize/data-table-resize-handle.d.ts +48 -0
  150. package/dist/components/data-table/resize/data-table-resize-handle.d.ts.map +1 -0
  151. package/dist/components/data-table/resize/data-table-resize-handle.js +115 -0
  152. package/dist/components/data-table/resize/data-table-resize-handle.js.map +1 -0
  153. package/dist/components/data-table/resize/use-data-table-resize-scroll.d.ts +18 -0
  154. package/dist/components/data-table/resize/use-data-table-resize-scroll.d.ts.map +1 -0
  155. package/dist/components/data-table/resize/use-data-table-resize-scroll.js +55 -0
  156. package/dist/components/data-table/resize/use-data-table-resize-scroll.js.map +1 -0
  157. package/dist/components/data-table/root/data-table-grid-classes.d.ts +10 -0
  158. package/dist/components/data-table/root/data-table-grid-classes.d.ts.map +1 -0
  159. package/dist/components/data-table/root/data-table-grid-classes.js +22 -0
  160. package/dist/components/data-table/root/data-table-grid-classes.js.map +1 -0
  161. package/dist/components/data-table/root/data-table-root.d.ts +41 -0
  162. package/dist/components/data-table/root/data-table-root.d.ts.map +1 -0
  163. package/dist/components/data-table/root/data-table-root.js +72 -0
  164. package/dist/components/data-table/root/data-table-root.js.map +1 -0
  165. package/dist/components/data-table/root/data-table-scroll-area.d.ts +21 -0
  166. package/dist/components/data-table/root/data-table-scroll-area.d.ts.map +1 -0
  167. package/dist/components/data-table/root/data-table-scroll-area.js +127 -0
  168. package/dist/components/data-table/root/data-table-scroll-area.js.map +1 -0
  169. package/dist/components/data-table/root/get-data-table-column-layout.d.ts +45 -0
  170. package/dist/components/data-table/root/get-data-table-column-layout.d.ts.map +1 -0
  171. package/dist/components/data-table/root/get-data-table-column-layout.js +55 -0
  172. package/dist/components/data-table/root/get-data-table-column-layout.js.map +1 -0
  173. package/dist/components/data-table/root/get-data-table-column-pinning.d.ts +46 -0
  174. package/dist/components/data-table/root/get-data-table-column-pinning.d.ts.map +1 -0
  175. package/dist/components/data-table/root/get-data-table-column-pinning.js +46 -0
  176. package/dist/components/data-table/root/get-data-table-column-pinning.js.map +1 -0
  177. package/dist/components/data-table/root/get-data-table-scroll-parent.d.ts +13 -0
  178. package/dist/components/data-table/root/get-data-table-scroll-parent.d.ts.map +1 -0
  179. package/dist/components/data-table/root/get-data-table-scroll-parent.js +20 -0
  180. package/dist/components/data-table/root/get-data-table-scroll-parent.js.map +1 -0
  181. package/dist/components/data-table/root/use-data-table-column-layout.d.ts +25 -0
  182. package/dist/components/data-table/root/use-data-table-column-layout.d.ts.map +1 -0
  183. package/dist/components/data-table/root/use-data-table-column-layout.js +106 -0
  184. package/dist/components/data-table/root/use-data-table-column-layout.js.map +1 -0
  185. package/dist/components/data-table/root/use-data-table-header-offset.d.ts +15 -0
  186. package/dist/components/data-table/root/use-data-table-header-offset.d.ts.map +1 -0
  187. package/dist/components/data-table/root/use-data-table-header-offset.js +35 -0
  188. package/dist/components/data-table/root/use-data-table-header-offset.js.map +1 -0
  189. package/dist/components/data-table/selection/data-table-row-checkbox.d.ts +33 -0
  190. package/dist/components/data-table/selection/data-table-row-checkbox.d.ts.map +1 -0
  191. package/dist/components/data-table/selection/data-table-row-checkbox.js +50 -0
  192. package/dist/components/data-table/selection/data-table-row-checkbox.js.map +1 -0
  193. package/dist/components/data-table/selection/data-table-select-all-checkbox.d.ts +31 -0
  194. package/dist/components/data-table/selection/data-table-select-all-checkbox.d.ts.map +1 -0
  195. package/dist/components/data-table/selection/data-table-select-all-checkbox.js +44 -0
  196. package/dist/components/data-table/selection/data-table-select-all-checkbox.js.map +1 -0
  197. package/dist/components/data-table/selection/selection-column-def.d.ts +54 -0
  198. package/dist/components/data-table/selection/selection-column-def.d.ts.map +1 -0
  199. package/dist/components/data-table/selection/selection-column-def.js +55 -0
  200. package/dist/components/data-table/selection/selection-column-def.js.map +1 -0
  201. package/dist/components/data-table/sorting/data-table-sort-indicator.d.ts +26 -0
  202. package/dist/components/data-table/sorting/data-table-sort-indicator.d.ts.map +1 -0
  203. package/dist/components/data-table/sorting/data-table-sort-indicator.js +64 -0
  204. package/dist/components/data-table/sorting/data-table-sort-indicator.js.map +1 -0
  205. package/dist/components/data-table/sorting/data-table-sort-trigger.d.ts +31 -0
  206. package/dist/components/data-table/sorting/data-table-sort-trigger.d.ts.map +1 -0
  207. package/dist/components/data-table/sorting/data-table-sort-trigger.js +46 -0
  208. package/dist/components/data-table/sorting/data-table-sort-trigger.js.map +1 -0
  209. package/dist/components/data-table/toolbar/data-table-density-select.d.ts +39 -0
  210. package/dist/components/data-table/toolbar/data-table-density-select.d.ts.map +1 -0
  211. package/dist/components/data-table/toolbar/data-table-density-select.js +60 -0
  212. package/dist/components/data-table/toolbar/data-table-density-select.js.map +1 -0
  213. package/dist/components/data-table/toolbar/data-table-sort-column-select.d.ts +47 -0
  214. package/dist/components/data-table/toolbar/data-table-sort-column-select.d.ts.map +1 -0
  215. package/dist/components/data-table/toolbar/data-table-sort-column-select.js +78 -0
  216. package/dist/components/data-table/toolbar/data-table-sort-column-select.js.map +1 -0
  217. package/dist/components/data-table/toolbar/data-table-sort-direction-select.d.ts +40 -0
  218. package/dist/components/data-table/toolbar/data-table-sort-direction-select.d.ts.map +1 -0
  219. package/dist/components/data-table/toolbar/data-table-sort-direction-select.js +66 -0
  220. package/dist/components/data-table/toolbar/data-table-sort-direction-select.js.map +1 -0
  221. package/dist/features/active-row/active-row-feature.d.ts +22 -0
  222. package/dist/features/active-row/active-row-feature.d.ts.map +1 -0
  223. package/dist/features/active-row/active-row-feature.js +55 -0
  224. package/dist/features/active-row/active-row-feature.js.map +1 -0
  225. package/dist/features/active-row/active-row-feature.types.d.ts +64 -0
  226. package/dist/features/active-row/active-row-feature.types.d.ts.map +1 -0
  227. package/dist/features/active-row/active-row-feature.types.js +0 -0
  228. package/dist/features/column-alignment/column-alignment-feature.d.ts +23 -0
  229. package/dist/features/column-alignment/column-alignment-feature.d.ts.map +1 -0
  230. package/dist/features/column-alignment/column-alignment-feature.js +34 -0
  231. package/dist/features/column-alignment/column-alignment-feature.js.map +1 -0
  232. package/dist/features/column-alignment/column-alignment-feature.types.d.ts +34 -0
  233. package/dist/features/column-alignment/column-alignment-feature.types.d.ts.map +1 -0
  234. package/dist/features/column-alignment/column-alignment-feature.types.js +0 -0
  235. package/dist/features/index.d.ts +9 -0
  236. package/dist/features/index.js +5 -0
  237. package/dist/features/loading/loading-feature.d.ts +30 -0
  238. package/dist/features/loading/loading-feature.d.ts.map +1 -0
  239. package/dist/features/loading/loading-feature.js +48 -0
  240. package/dist/features/loading/loading-feature.js.map +1 -0
  241. package/dist/features/loading/loading-feature.types.d.ts +50 -0
  242. package/dist/features/loading/loading-feature.types.d.ts.map +1 -0
  243. package/dist/features/loading/loading-feature.types.js +0 -0
  244. package/dist/features/row-density/row-density-feature.d.ts +26 -0
  245. package/dist/features/row-density/row-density-feature.d.ts.map +1 -0
  246. package/dist/features/row-density/row-density-feature.js +44 -0
  247. package/dist/features/row-density/row-density-feature.js.map +1 -0
  248. package/dist/features/row-density/row-density-feature.types.d.ts +53 -0
  249. package/dist/features/row-density/row-density-feature.types.d.ts.map +1 -0
  250. package/dist/features/row-density/row-density-feature.types.js +0 -0
  251. package/dist/types/index.d.ts +2 -0
  252. package/dist/types/index.js +0 -0
  253. package/dist/types/table-with.d.ts +96 -0
  254. package/dist/types/table-with.d.ts.map +1 -0
  255. package/dist/types/table-with.js +0 -0
  256. package/dist/utils/get-default-column-label.d.ts +17 -0
  257. package/dist/utils/get-default-column-label.d.ts.map +1 -0
  258. package/dist/utils/get-default-column-label.js +18 -0
  259. package/dist/utils/get-default-column-label.js.map +1 -0
  260. package/dist/utils/has-feature.d.ts +54 -0
  261. package/dist/utils/has-feature.d.ts.map +1 -0
  262. package/dist/utils/has-feature.js +55 -0
  263. package/dist/utils/has-feature.js.map +1 -0
  264. package/dist/utils/index.d.ts +3 -0
  265. package/dist/utils/index.js +3 -0
  266. package/package.json +80 -3
  267. package/README.md +0 -3
@@ -0,0 +1,150 @@
1
+ import { hasRowFeature } from "../../../utils/has-feature.js";
2
+ import { focusDataTableRow, getDataTableRowKeyTarget } from "./data-table-row-focus.js";
3
+ import { DATA_TABLE_GRID_CLASS_NAMES } from "../root/data-table-grid-classes.js";
4
+ import { DataTableCell } from "./data-table-cell.js";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import { mergeProps, useRender } from "@base-ui/react";
7
+ import { shallow, useSelector } from "@tanstack/react-store";
8
+ import { mergeTwClassNames } from "@lucasbernardosn/react-ui/utils";
9
+ import { Fragment as Fragment$1 } from "react";
10
+ //#region src/components/data-table/body/data-table-row.tsx
11
+ /**
12
+ * Uma linha do corpo (`role="row"`). É um grid com as colunas do `--data-table-template`, que o
13
+ * `DataTable.Root` escreve.
14
+ *
15
+ * Com render-prop ou sem `children`, faz o laço das células sozinha: assina as próprias células e
16
+ * re-renderiza quando a ordem, a visibilidade ou o pinning das colunas mudam, que não mudam o row
17
+ * model e não passam pelo `DataTable.Body`. Com `columnVisibilityFeature`, são as células
18
+ * visíveis; sem ela, todas. Com `columnPinningFeature`, vêm na ordem das regiões: as fixadas no
19
+ * início, as do centro e as fixadas no fim.
20
+ *
21
+ * Com `rowSelectionFeature`, a linha selecionada ganha `data-selected` e o fundo destacado, e com
22
+ * `activeRowFeature`, também o `aria-selected`. O clique na linha não seleciona: o `onClick` fica
23
+ * livre, e a seleção é do `DataTable.RowCheckbox` e do Espaço.
24
+ *
25
+ * Com `activeRowFeature`, entra na navegação por teclado. A linha ativa tem o ponto de Tab (sem
26
+ * ela no row model, a primeira), e receber o foco, pelo teclado ou pelo clique, torna esta a
27
+ * ativa, marcada com `data-active`. ↑↓, Home, End, PageUp e PageDown movem o foco entre as
28
+ * linhas, e o Espaço alterna a seleção, com Shift para o intervalo. Os atalhos são do app, no
29
+ * `onKeyDown`, que roda antes: um `preventDefault()` cancela o da linha. Num campo de texto de
30
+ * dentro, as setas ficam com o campo.
31
+ *
32
+ * O fundo fica na variável `--data-table-row-background`, que as células fixadas repetem: o
33
+ * hover e a selecionada a trocam para `gray-3`, e as duas juntas, para `gray-4`. Para colorir uma
34
+ * linha, troque a variável, e não use `bg-*`, que deixaria as fixadas com a cor antiga. A cor do
35
+ * texto fica na linha, e as células herdam.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * <DataTable.Row
40
+ * row={row}
41
+ * onClick={() => openCustomer(row.original)}
42
+ * onKeyDown={(event) => {
43
+ * if (event.key === 'Enter') {
44
+ * openCustomer(row.original);
45
+ * }
46
+ * }}
47
+ * className={
48
+ * row.original.overdue
49
+ * ? '[--data-table-row-background:var(--color-gray-2)] text-gray-11'
50
+ * : undefined
51
+ * }
52
+ * >
53
+ * {(cell) => <DataTable.Cell cell={cell} />}
54
+ * </DataTable.Row>
55
+ * ```
56
+ */
57
+ const DataTableRow = (props) => {
58
+ const { row, render, className, children, ...rest } = props;
59
+ const cells = useSelector(row.table.store, () => hasRowFeature(row, "columnPinningFeature") ? [
60
+ row.getStartVisibleCells(),
61
+ row.getCenterVisibleCells(),
62
+ row.getEndVisibleCells()
63
+ ] : hasRowFeature(row, "columnVisibilityFeature") ? [row.getVisibleCells()] : [row.getAllCells()], { compare: shallow }).flat();
64
+ /**
65
+ * Só re-renderiza quando esta linha é marcada ou desmarcada. A seleção é opcional, então assina
66
+ * o store; sem `rowSelectionFeature`, nenhuma linha fica selecionada.
67
+ */
68
+ const isSelected = useSelector(row.table.store, () => hasRowFeature(row, "rowSelectionFeature") && row.getIsSelected());
69
+ /**
70
+ * O ponto de Tab da tabela: a linha ativa ou, sem ela no row model, a primeira. Re-renderiza
71
+ * quando o ponto de Tab entra ou sai daqui. A navegação é opcional, então assina o store; sem
72
+ * `activeRowFeature`, nenhuma linha entra no Tab.
73
+ */
74
+ const isTabStop = useSelector(row.table.store, () => {
75
+ if (!hasRowFeature(row, "activeRowFeature")) return false;
76
+ const activeRow = row.table.getActiveRow();
77
+ return activeRow ? activeRow.id === row.id : row.table.getRowModel().rows[0]?.id === row.id;
78
+ });
79
+ /** Só re-renderiza quando esta linha vira ou deixa de ser a ativa. */
80
+ const isActive = useSelector(row.table.store, () => hasRowFeature(row, "activeRowFeature") && row.getIsActive());
81
+ /** Receber o foco, nela ou num controle de dentro, torna esta a linha ativa. */
82
+ const handleFocus = () => {
83
+ if (hasRowFeature(row, "activeRowFeature") && !row.getIsActive()) row.table.setActiveRowId(row.id);
84
+ };
85
+ /** As teclas da navegação. O `onKeyDown` do app roda antes e cancela com `preventDefault()`. */
86
+ const handleKeyDown = (event) => {
87
+ if (!hasRowFeature(row, "activeRowFeature") || event.defaultPrevented) return;
88
+ /** Na própria linha: num controle de dentro, como o checkbox, o Espaço é dele. */
89
+ if (event.key === " " && event.target === event.currentTarget) {
90
+ if (hasRowFeature(row, "rowSelectionFeature") && row.getCanSelect()) {
91
+ event.preventDefault();
92
+ /** O handler do checkbox: lê o Shift do evento, para o intervalo, e move a âncora. */
93
+ row.getToggleSelectedHandler()({
94
+ target: { checked: !row.getIsSelected() },
95
+ nativeEvent: event.nativeEvent
96
+ });
97
+ }
98
+ return;
99
+ }
100
+ const targetRow = getDataTableRowKeyTarget(event.currentTarget, event);
101
+ if (targetRow) {
102
+ event.preventDefault();
103
+ focusDataTableRow(targetRow);
104
+ }
105
+ };
106
+ const isNavigable = hasRowFeature(row, "activeRowFeature");
107
+ /** Com render-prop ou sem `children`, o laço é daqui; com nós comuns, de quem usa. */
108
+ const content = typeof children === "function" || children === void 0 ? cells.map((cell) => /* @__PURE__ */ jsx(Fragment$1, { children: children === void 0 ? /* @__PURE__ */ jsx(DataTableCell, { cell }) : children(cell) }, cell.id)) : children;
109
+ const baseProps = {
110
+ "data-component": "DataTable.Row",
111
+ "data-selected": isSelected ? "" : void 0,
112
+ "data-active": isActive ? "" : void 0,
113
+ role: "row",
114
+ "aria-selected": isNavigable && hasRowFeature(row, "rowSelectionFeature") ? isSelected : void 0,
115
+ tabIndex: isNavigable ? isTabStop ? 0 : -1 : void 0,
116
+ onFocus: handleFocus,
117
+ onKeyDown: handleKeyDown,
118
+ className: mergeTwClassNames([
119
+ "relative",
120
+ DATA_TABLE_GRID_CLASS_NAMES,
121
+ "last:border-b-0",
122
+ "[--data-table-row-background:var(--color-gray-1)]",
123
+ "hover:[--data-table-row-background:var(--color-gray-3)]",
124
+ "data-selected:[--data-table-row-background:var(--color-gray-3)]",
125
+ "data-selected:hover:[--data-table-row-background:var(--color-gray-4)]",
126
+ "bg-(--data-table-row-background)",
127
+ "text-gray-12",
128
+ "outline-none",
129
+ "after:pointer-events-none",
130
+ "after:absolute",
131
+ "after:inset-0",
132
+ "after:z-2",
133
+ "after:content-[\"\"]",
134
+ "focus-within:after:outline-2",
135
+ "focus-within:after:-outline-offset-2",
136
+ "focus-within:after:outline-gray-12"
137
+ ], className),
138
+ children: content
139
+ };
140
+ return useRender({
141
+ render,
142
+ defaultTagName: "div",
143
+ props: mergeProps(baseProps, rest)
144
+ });
145
+ };
146
+ DataTableRow.displayName = "DataTable.Row";
147
+ //#endregion
148
+ export { DataTableRow };
149
+
150
+ //# sourceMappingURL=data-table-row.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-row.js","names":["Fragment"],"sources":["../../../../src/components/data-table/body/data-table-row.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { shallow, useSelector } from '@tanstack/react-store';\nimport type { Cell, Row, RowData, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport { Fragment } from 'react';\nimport { hasRowFeature } from '../../../utils';\nimport { DATA_TABLE_GRID_CLASS_NAMES } from '../root/data-table-grid-classes';\nimport { DataTableCell } from './data-table-cell';\nimport {\n focusDataTableRow,\n getDataTableRowKeyTarget,\n} from './data-table-row-focus';\n\nexport type DataTableRowProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** A linha do row model. */\n row: Row<TFeatures, TData>;\n /**\n * Uma função que recebe cada célula visível e devolve o elemento dela. Com nós comuns, quem\n * usa faz o laço.\n * @default (cell) => <DataTable.Cell cell={cell} />\n */\n children?:\n | React.ReactNode\n | ((cell: Cell<TFeatures, TData>) => React.ReactNode);\n }\n>;\n\n/**\n * Uma linha do corpo (`role=\"row\"`). É um grid com as colunas do `--data-table-template`, que o\n * `DataTable.Root` escreve.\n *\n * Com render-prop ou sem `children`, faz o laço das células sozinha: assina as próprias células e\n * re-renderiza quando a ordem, a visibilidade ou o pinning das colunas mudam, que não mudam o row\n * model e não passam pelo `DataTable.Body`. Com `columnVisibilityFeature`, são as células\n * visíveis; sem ela, todas. Com `columnPinningFeature`, vêm na ordem das regiões: as fixadas no\n * início, as do centro e as fixadas no fim.\n *\n * Com `rowSelectionFeature`, a linha selecionada ganha `data-selected` e o fundo destacado, e com\n * `activeRowFeature`, também o `aria-selected`. O clique na linha não seleciona: o `onClick` fica\n * livre, e a seleção é do `DataTable.RowCheckbox` e do Espaço.\n *\n * Com `activeRowFeature`, entra na navegação por teclado. A linha ativa tem o ponto de Tab (sem\n * ela no row model, a primeira), e receber o foco, pelo teclado ou pelo clique, torna esta a\n * ativa, marcada com `data-active`. ↑↓, Home, End, PageUp e PageDown movem o foco entre as\n * linhas, e o Espaço alterna a seleção, com Shift para o intervalo. Os atalhos são do app, no\n * `onKeyDown`, que roda antes: um `preventDefault()` cancela o da linha. Num campo de texto de\n * dentro, as setas ficam com o campo.\n *\n * O fundo fica na variável `--data-table-row-background`, que as células fixadas repetem: o\n * hover e a selecionada a trocam para `gray-3`, e as duas juntas, para `gray-4`. Para colorir uma\n * linha, troque a variável, e não use `bg-*`, que deixaria as fixadas com a cor antiga. A cor do\n * texto fica na linha, e as células herdam.\n *\n * @example\n * ```tsx\n * <DataTable.Row\n * row={row}\n * onClick={() => openCustomer(row.original)}\n * onKeyDown={(event) => {\n * if (event.key === 'Enter') {\n * openCustomer(row.original);\n * }\n * }}\n * className={\n * row.original.overdue\n * ? '[--data-table-row-background:var(--color-gray-2)] text-gray-11'\n * : undefined\n * }\n * >\n * {(cell) => <DataTable.Cell cell={cell} />}\n * </DataTable.Row>\n * ```\n */\nexport const DataTableRow = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableRowProps<TFeatures, TData>,\n) => {\n const { row, render, className, children, ...rest } = props;\n\n /**\n * As listas que o TanStack memoiza, numa tupla: o `shallow` compara item a item, e só\n * re-renderiza quando uma delas muda com as colunas. Todas seguem a ordem dos headers folha, que\n * é a do template, e as células caem nos tracks certos. Com pinning, as três regiões, que\n * ordenam as fixadas mesmo sem `columnVisibilityFeature`.\n */\n const cellGroups = useSelector(\n row.table.store,\n () =>\n hasRowFeature(row, 'columnPinningFeature')\n ? [\n row.getStartVisibleCells(),\n row.getCenterVisibleCells(),\n row.getEndVisibleCells(),\n ]\n : hasRowFeature(row, 'columnVisibilityFeature')\n ? [row.getVisibleCells()]\n : [row.getAllCells()],\n { compare: shallow },\n );\n\n const cells = cellGroups.flat();\n\n /**\n * Só re-renderiza quando esta linha é marcada ou desmarcada. A seleção é opcional, então assina\n * o store; sem `rowSelectionFeature`, nenhuma linha fica selecionada.\n */\n const isSelected = useSelector(\n row.table.store,\n () => hasRowFeature(row, 'rowSelectionFeature') && row.getIsSelected(),\n );\n\n /**\n * O ponto de Tab da tabela: a linha ativa ou, sem ela no row model, a primeira. Re-renderiza\n * quando o ponto de Tab entra ou sai daqui. A navegação é opcional, então assina o store; sem\n * `activeRowFeature`, nenhuma linha entra no Tab.\n */\n const isTabStop = useSelector(row.table.store, () => {\n if (!hasRowFeature(row, 'activeRowFeature')) {\n return false;\n }\n\n const activeRow = row.table.getActiveRow();\n\n return activeRow\n ? activeRow.id === row.id\n : row.table.getRowModel().rows[0]?.id === row.id;\n });\n\n /** Só re-renderiza quando esta linha vira ou deixa de ser a ativa. */\n const isActive = useSelector(\n row.table.store,\n () => hasRowFeature(row, 'activeRowFeature') && row.getIsActive(),\n );\n\n /** Receber o foco, nela ou num controle de dentro, torna esta a linha ativa. */\n const handleFocus = () => {\n if (hasRowFeature(row, 'activeRowFeature') && !row.getIsActive()) {\n row.table.setActiveRowId(row.id);\n }\n };\n\n /** As teclas da navegação. O `onKeyDown` do app roda antes e cancela com `preventDefault()`. */\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!hasRowFeature(row, 'activeRowFeature') || event.defaultPrevented) {\n return;\n }\n\n /** Na própria linha: num controle de dentro, como o checkbox, o Espaço é dele. */\n if (event.key === ' ' && event.target === event.currentTarget) {\n if (hasRowFeature(row, 'rowSelectionFeature') && row.getCanSelect()) {\n event.preventDefault();\n\n /** O handler do checkbox: lê o Shift do evento, para o intervalo, e move a âncora. */\n row.getToggleSelectedHandler()({\n target: { checked: !row.getIsSelected() },\n nativeEvent: event.nativeEvent,\n });\n }\n\n return;\n }\n\n const targetRow = getDataTableRowKeyTarget(event.currentTarget, event);\n\n if (targetRow) {\n event.preventDefault();\n focusDataTableRow(targetRow);\n }\n };\n\n const isNavigable = hasRowFeature(row, 'activeRowFeature');\n\n /** Com render-prop ou sem `children`, o laço é daqui; com nós comuns, de quem usa. */\n const content =\n typeof children === 'function' || children === undefined\n ? cells.map((cell) => (\n <Fragment key={cell.id}>\n {children === undefined ? (\n <DataTableCell cell={cell} />\n ) : (\n children(cell)\n )}\n </Fragment>\n ))\n : children;\n\n const baseProps = {\n 'data-component': 'DataTable.Row',\n 'data-selected': isSelected ? '' : undefined,\n 'data-active': isActive ? '' : undefined,\n role: 'row',\n // Só no `grid`: o ARIA não define o atributo na linha de uma `table`, e o leitor o ignora.\n 'aria-selected':\n isNavigable && hasRowFeature(row, 'rowSelectionFeature')\n ? isSelected\n : undefined,\n tabIndex: isNavigable ? (isTabStop ? 0 : -1) : undefined,\n onFocus: handleFocus,\n onKeyDown: handleKeyDown,\n className: mergeTwClassNames(\n [\n // O anel de foco se posiciona por aqui.\n 'relative',\n\n DATA_TABLE_GRID_CLASS_NAMES,\n // Sem a linha horizontal na última: embaixo dela já vem a borda da área de rolagem, e as\n // duas somariam 2px.\n 'last:border-b-0',\n\n // O fundo numa variável, que as células fixadas repetem para ficarem opacas. A selecionada\n // e o hover têm a mesma cor, e a selecionada com hover sobe um passo: sem isso, passar o\n // mouse por ela não mudaria nada.\n '[--data-table-row-background:var(--color-gray-1)]',\n 'hover:[--data-table-row-background:var(--color-gray-3)]',\n 'data-selected:[--data-table-row-background:var(--color-gray-3)]',\n 'data-selected:hover:[--data-table-row-background:var(--color-gray-4)]',\n 'bg-(--data-table-row-background)',\n\n 'text-gray-12',\n\n // O anel de foco, com o foco na linha ou num controle de dentro, pelo teclado ou pelo\n // clique: com `focus-visible`, o clique tornaria a linha ativa sem mostrar qual é. Num\n // `::after` por cima das células fixadas (`z-1`), que cobririam o `outline` e o\n // `box-shadow` da própria linha. Por dentro: a linha seguinte cobriria o que sai por baixo.\n 'outline-none',\n 'after:pointer-events-none',\n 'after:absolute',\n 'after:inset-0',\n 'after:z-2',\n 'after:content-[\"\"]',\n 'focus-within:after:outline-2',\n 'focus-within:after:-outline-offset-2',\n 'focus-within:after:outline-gray-12',\n ],\n className,\n ),\n children: content,\n };\n\n return useRender({\n render,\n defaultTagName: 'div',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableRow.displayName = 'DataTable.Row';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,MAAa,gBAIX,UACG;CACH,MAAM,EAAE,KAAK,QAAQ,WAAW,UAAU,GAAG,SAAS;CAuBtD,MAAM,QAfa,YACjB,IAAI,MAAM,aAER,cAAc,KAAK,sBAAsB,IACrC;EACE,IAAI,qBAAqB;EACzB,IAAI,sBAAsB;EAC1B,IAAI,mBAAmB;CACzB,IACA,cAAc,KAAK,yBAAyB,IAC1C,CAAC,IAAI,gBAAgB,CAAC,IACtB,CAAC,IAAI,YAAY,CAAC,GAC1B,EAAE,SAAS,QAAQ,CAGE,CAAC,CAAC,KAAK;;;;;CAM9B,MAAM,aAAa,YACjB,IAAI,MAAM,aACJ,cAAc,KAAK,qBAAqB,KAAK,IAAI,cAAc,CACvE;;;;;;CAOA,MAAM,YAAY,YAAY,IAAI,MAAM,aAAa;EACnD,IAAI,CAAC,cAAc,KAAK,kBAAkB,GACxC,OAAO;EAGT,MAAM,YAAY,IAAI,MAAM,aAAa;EAEzC,OAAO,YACH,UAAU,OAAO,IAAI,KACrB,IAAI,MAAM,YAAY,CAAC,CAAC,KAAK,EAAE,EAAE,OAAO,IAAI;CAClD,CAAC;;CAGD,MAAM,WAAW,YACf,IAAI,MAAM,aACJ,cAAc,KAAK,kBAAkB,KAAK,IAAI,YAAY,CAClE;;CAGA,MAAM,oBAAoB;EACxB,IAAI,cAAc,KAAK,kBAAkB,KAAK,CAAC,IAAI,YAAY,GAC7D,IAAI,MAAM,eAAe,IAAI,EAAE;CAEnC;;CAGA,MAAM,iBAAiB,UAA+C;EACpE,IAAI,CAAC,cAAc,KAAK,kBAAkB,KAAK,MAAM,kBACnD;;EAIF,IAAI,MAAM,QAAQ,OAAO,MAAM,WAAW,MAAM,eAAe;GAC7D,IAAI,cAAc,KAAK,qBAAqB,KAAK,IAAI,aAAa,GAAG;IACnE,MAAM,eAAe;;IAGrB,IAAI,yBAAyB,CAAC,CAAC;KAC7B,QAAQ,EAAE,SAAS,CAAC,IAAI,cAAc,EAAE;KACxC,aAAa,MAAM;IACrB,CAAC;GACH;GAEA;EACF;EAEA,MAAM,YAAY,yBAAyB,MAAM,eAAe,KAAK;EAErE,IAAI,WAAW;GACb,MAAM,eAAe;GACrB,kBAAkB,SAAS;EAC7B;CACF;CAEA,MAAM,cAAc,cAAc,KAAK,kBAAkB;;CAGzD,MAAM,UACJ,OAAO,aAAa,cAAc,aAAa,KAAA,IAC3C,MAAM,KAAK,SACT,oBAACA,YAAD,EAAA,UACG,aAAa,KAAA,IACZ,oBAAC,eAAD,EAAqB,KAAO,CAAA,IAE5B,SAAS,IAAI,EAEP,GANK,KAAK,EAMV,CACX,IACD;CAEN,MAAM,YAAY;EAChB,kBAAkB;EAClB,iBAAiB,aAAa,KAAK,KAAA;EACnC,eAAe,WAAW,KAAK,KAAA;EAC/B,MAAM;EAEN,iBACE,eAAe,cAAc,KAAK,qBAAqB,IACnD,aACA,KAAA;EACN,UAAU,cAAe,YAAY,IAAI,KAAM,KAAA;EAC/C,SAAS;EACT,WAAW;EACX,WAAW,kBACT;GAEE;GAEA;GAGA;GAKA;GACA;GACA;GACA;GACA;GAEA;GAMA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,GACA,SACF;EACA,UAAU;CACZ;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,aAAa,cAAc"}
@@ -0,0 +1,19 @@
1
+ import { Row, RowData, Table, TableFeatures } from "@tanstack/react-table";
2
+ import React from "react";
3
+ //#region src/components/data-table/body/use-data-table-row-focus-recovery.d.ts
4
+ /**
5
+ * Devolve o foco a uma linha quando a que o tinha sai do corpo: apagada, de outra página,
6
+ * filtrada ou movida pela ordenação. Sem isto, o foco cai no `body`, e o teclado perde a tabela.
7
+ *
8
+ * O foco vai para a linha ativa, se ela continua no corpo; senão, para a que ficou na posição da
9
+ * que saiu, ou para a última. Com o foco fora da tabela, nada muda. Só com `activeRowFeature`.
10
+ *
11
+ * Devolve o ref e os handlers de foco do elemento do corpo.
12
+ */
13
+ export declare const useDataTableRowFocusRecovery: <TFeatures extends TableFeatures, TData extends RowData>(table: Table<TFeatures, TData>, rows: Row<TFeatures, TData>[]) => {
14
+ ref: React.RefObject<HTMLDivElement | null>;
15
+ onFocus: (event: React.FocusEvent<HTMLDivElement>) => void;
16
+ onBlur: (event: React.FocusEvent<HTMLDivElement>) => void;
17
+ };
18
+ //#endregion
19
+ //# sourceMappingURL=use-data-table-row-focus-recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-data-table-row-focus-recovery.d.ts","names":[],"sources":["../../../../src/components/data-table/body/use-data-table-row-focus-recovery.ts"],"mappings":";;;;;;;;;;;;qBAkBa,+BACX,kBAAkB,eAClB,cAAc,SAEd,OAAO,MAAM,WAAW,QACxB,MAAM,IAAI,WAAW;;EAQG,UAAA,OAAA,MAAM,WAAW;EAUlB,SAAA,OAAA,MAAM,WAAW"}
@@ -0,0 +1,64 @@
1
+ import { hasTableFeature } from "../../../utils/has-feature.js";
2
+ import { focusDataTableRow, getDataTableRowElements } from "./data-table-row-focus.js";
3
+ import { useLayoutEffect, useRef } from "react";
4
+ //#region src/components/data-table/body/use-data-table-row-focus-recovery.ts
5
+ /**
6
+ * Devolve o foco a uma linha quando a que o tinha sai do corpo: apagada, de outra página,
7
+ * filtrada ou movida pela ordenação. Sem isto, o foco cai no `body`, e o teclado perde a tabela.
8
+ *
9
+ * O foco vai para a linha ativa, se ela continua no corpo; senão, para a que ficou na posição da
10
+ * que saiu, ou para a última. Com o foco fora da tabela, nada muda. Só com `activeRowFeature`.
11
+ *
12
+ * Devolve o ref e os handlers de foco do elemento do corpo.
13
+ */
14
+ const useDataTableRowFocusRecovery = (table, rows) => {
15
+ /** O elemento do corpo. */
16
+ const ref = useRef(null);
17
+ /** Se o foco está numa linha daqui, e a posição dela, gravados a cada foco recebido. */
18
+ const focusRef = useRef({
19
+ isInside: false,
20
+ index: 0
21
+ });
22
+ const onFocus = (event) => {
23
+ const rowElement = event.target.closest("[role=\"row\"]");
24
+ const index = rowElement instanceof HTMLElement ? getDataTableRowElements(event.currentTarget).indexOf(rowElement) : -1;
25
+ focusRef.current = {
26
+ isInside: true,
27
+ index: Math.max(index, 0)
28
+ };
29
+ };
30
+ const onBlur = (event) => {
31
+ if (event.relatedTarget && event.currentTarget.contains(event.relatedTarget)) return;
32
+ /**
33
+ * O Chrome também avisa a saída quando a linha com foco é removida, antes de tirá-la do DOM.
34
+ * Só depois do commit dá para separar: se o efeito abaixo devolveu o foco, ele não saiu.
35
+ */
36
+ queueMicrotask(() => {
37
+ focusRef.current.isInside = Boolean(ref.current?.contains(document.activeElement));
38
+ });
39
+ };
40
+ /**
41
+ * Depois de cada mudança das linhas, já com o DOM atualizado. Layout effect, e não effect, para
42
+ * o foco voltar antes da pintura.
43
+ */
44
+ useLayoutEffect(() => {
45
+ const element = ref.current;
46
+ const { activeElement } = document;
47
+ if (!(element && focusRef.current.isInside) || activeElement && activeElement !== document.body || !hasTableFeature(table, "activeRowFeature")) return;
48
+ const rowElements = getDataTableRowElements(element);
49
+ const activeRowId = table.getActiveRow()?.id;
50
+ const activeIndex = rows.findIndex((row) => row.id === activeRowId);
51
+ const targetRow = rowElements[activeIndex >= 0 ? activeIndex : Math.min(focusRef.current.index, rowElements.length - 1)];
52
+ if (targetRow) focusDataTableRow(targetRow);
53
+ else focusRef.current.isInside = false;
54
+ }, [table, rows]);
55
+ return {
56
+ ref,
57
+ onFocus,
58
+ onBlur
59
+ };
60
+ };
61
+ //#endregion
62
+ export { useDataTableRowFocusRecovery };
63
+
64
+ //# sourceMappingURL=use-data-table-row-focus-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-data-table-row-focus-recovery.js","names":[],"sources":["../../../../src/components/data-table/body/use-data-table-row-focus-recovery.ts"],"sourcesContent":["import type { Row, RowData, Table, TableFeatures } from '@tanstack/react-table';\nimport type React from 'react';\nimport { useLayoutEffect, useRef } from 'react';\nimport { hasTableFeature } from '../../../utils';\nimport {\n focusDataTableRow,\n getDataTableRowElements,\n} from './data-table-row-focus';\n\n/**\n * Devolve o foco a uma linha quando a que o tinha sai do corpo: apagada, de outra página,\n * filtrada ou movida pela ordenação. Sem isto, o foco cai no `body`, e o teclado perde a tabela.\n *\n * O foco vai para a linha ativa, se ela continua no corpo; senão, para a que ficou na posição da\n * que saiu, ou para a última. Com o foco fora da tabela, nada muda. Só com `activeRowFeature`.\n *\n * Devolve o ref e os handlers de foco do elemento do corpo.\n */\nexport const useDataTableRowFocusRecovery = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n table: Table<TFeatures, TData>,\n rows: Row<TFeatures, TData>[],\n) => {\n /** O elemento do corpo. */\n const ref = useRef<HTMLDivElement | null>(null);\n\n /** Se o foco está numa linha daqui, e a posição dela, gravados a cada foco recebido. */\n const focusRef = useRef({ isInside: false, index: 0 });\n\n const onFocus = (event: React.FocusEvent<HTMLDivElement>) => {\n const rowElement = event.target.closest('[role=\"row\"]');\n const index =\n rowElement instanceof HTMLElement\n ? getDataTableRowElements(event.currentTarget).indexOf(rowElement)\n : -1;\n\n focusRef.current = { isInside: true, index: Math.max(index, 0) };\n };\n\n const onBlur = (event: React.FocusEvent<HTMLDivElement>) => {\n if (\n event.relatedTarget &&\n event.currentTarget.contains(event.relatedTarget)\n ) {\n return;\n }\n\n /**\n * O Chrome também avisa a saída quando a linha com foco é removida, antes de tirá-la do DOM.\n * Só depois do commit dá para separar: se o efeito abaixo devolveu o foco, ele não saiu.\n */\n queueMicrotask(() => {\n focusRef.current.isInside = Boolean(\n ref.current?.contains(document.activeElement),\n );\n });\n };\n\n /**\n * Depois de cada mudança das linhas, já com o DOM atualizado. Layout effect, e não effect, para\n * o foco voltar antes da pintura.\n */\n useLayoutEffect(() => {\n const element = ref.current;\n const { activeElement } = document;\n\n if (\n !(element && focusRef.current.isInside) ||\n (activeElement && activeElement !== document.body) ||\n !hasTableFeature(table, 'activeRowFeature')\n ) {\n return;\n }\n\n const rowElements = getDataTableRowElements(element);\n const activeRowId = table.getActiveRow()?.id;\n const activeIndex = rows.findIndex((row) => row.id === activeRowId);\n const targetRow =\n rowElements[\n activeIndex >= 0\n ? activeIndex\n : Math.min(focusRef.current.index, rowElements.length - 1)\n ];\n\n if (targetRow) {\n focusDataTableRow(targetRow);\n } else {\n focusRef.current.isInside = false;\n }\n }, [table, rows]);\n\n return { ref, onFocus, onBlur };\n};\n"],"mappings":";;;;;;;;;;;;;AAkBA,MAAa,gCAIX,OACA,SACG;;CAEH,MAAM,MAAM,OAA8B,IAAI;;CAG9C,MAAM,WAAW,OAAO;EAAE,UAAU;EAAO,OAAO;CAAE,CAAC;CAErD,MAAM,WAAW,UAA4C;EAC3D,MAAM,aAAa,MAAM,OAAO,QAAQ,gBAAc;EACtD,MAAM,QACJ,sBAAsB,cAClB,wBAAwB,MAAM,aAAa,CAAC,CAAC,QAAQ,UAAU,IAC/D;EAEN,SAAS,UAAU;GAAE,UAAU;GAAM,OAAO,KAAK,IAAI,OAAO,CAAC;EAAE;CACjE;CAEA,MAAM,UAAU,UAA4C;EAC1D,IACE,MAAM,iBACN,MAAM,cAAc,SAAS,MAAM,aAAa,GAEhD;;;;;EAOF,qBAAqB;GACnB,SAAS,QAAQ,WAAW,QAC1B,IAAI,SAAS,SAAS,SAAS,aAAa,CAC9C;EACF,CAAC;CACH;;;;;CAMA,sBAAsB;EACpB,MAAM,UAAU,IAAI;EACpB,MAAM,EAAE,kBAAkB;EAE1B,IACE,EAAE,WAAW,SAAS,QAAQ,aAC7B,iBAAiB,kBAAkB,SAAS,QAC7C,CAAC,gBAAgB,OAAO,kBAAkB,GAE1C;EAGF,MAAM,cAAc,wBAAwB,OAAO;EACnD,MAAM,cAAc,MAAM,aAAa,CAAC,EAAE;EAC1C,MAAM,cAAc,KAAK,WAAW,QAAQ,IAAI,OAAO,WAAW;EAClE,MAAM,YACJ,YACE,eAAe,IACX,cACA,KAAK,IAAI,SAAS,QAAQ,OAAO,YAAY,SAAS,CAAC;EAG/D,IAAI,WACF,kBAAkB,SAAS;OAE3B,SAAS,QAAQ,WAAW;CAEhC,GAAG,CAAC,OAAO,IAAI,CAAC;CAEhB,OAAO;EAAE;EAAK;EAAS;CAAO;AAChC"}
@@ -0,0 +1,25 @@
1
+ import { useRender } from "@base-ui/react";
2
+ //#region src/components/data-table/header/data-table-header-button.d.ts
3
+ export type DataTableHeaderButtonProps = useRender.ComponentProps<'button'>;
4
+ /**
5
+ * O botão do tamanho da célula do header, sem ação: a base do `DataTable.SortTrigger` e de outros
6
+ * gatilhos do header, como o de um popover da coluna. Ocupa a `DataTable.HeaderCell` inteira; nas
7
+ * bordas, a área de agarre do `DataTable.ResizeHandle` fica por cima. Alinha o conteúdo pelo
8
+ * `data-align` da `DataTable.HeaderCell`, sem precisar do header.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <Popover.Root>
13
+ * <Popover.Trigger render={<DataTable.HeaderButton />}>
14
+ * <DataTable.HeaderContent header={header} />
15
+ * </Popover.Trigger>
16
+ * …
17
+ * </Popover.Root>
18
+ * ```
19
+ */
20
+ export declare const DataTableHeaderButton: {
21
+ (props: DataTableHeaderButtonProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
22
+ displayName: string;
23
+ };
24
+ //#endregion
25
+ //# sourceMappingURL=data-table-header-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-header-button.d.ts","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-button.tsx"],"mappings":";;YAGY,6BAA6B,UAAU;;;;;;;;;;;;;;;;;qBAkBtC;GAAgC,OAAA,6CAA0B,+CAAA"}
@@ -0,0 +1,57 @@
1
+ import { mergeProps, useRender } from "@base-ui/react";
2
+ import { mergeTwClassNames } from "@lucasbernardosn/react-ui/utils";
3
+ //#region src/components/data-table/header/data-table-header-button.tsx
4
+ /**
5
+ * O botão do tamanho da célula do header, sem ação: a base do `DataTable.SortTrigger` e de outros
6
+ * gatilhos do header, como o de um popover da coluna. Ocupa a `DataTable.HeaderCell` inteira; nas
7
+ * bordas, a área de agarre do `DataTable.ResizeHandle` fica por cima. Alinha o conteúdo pelo
8
+ * `data-align` da `DataTable.HeaderCell`, sem precisar do header.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <Popover.Root>
13
+ * <Popover.Trigger render={<DataTable.HeaderButton />}>
14
+ * <DataTable.HeaderContent header={header} />
15
+ * </Popover.Trigger>
16
+ * …
17
+ * </Popover.Root>
18
+ * ```
19
+ */
20
+ const DataTableHeaderButton = (props) => {
21
+ const { render, className, ...rest } = props;
22
+ const baseProps = {
23
+ "data-component": "DataTable.HeaderButton",
24
+ type: render === void 0 ? "button" : void 0,
25
+ className: mergeTwClassNames([
26
+ "flex-1",
27
+ "self-stretch",
28
+ "min-w-0",
29
+ "-mx-(--data-table-cell-padding)",
30
+ "px-(--data-table-cell-padding)",
31
+ "flex",
32
+ "items-center",
33
+ "gap-1",
34
+ "in-data-[align=center]:justify-center",
35
+ "in-data-[align=end]:[justify-content:end]",
36
+ "text-start",
37
+ "enabled:cursor-pointer",
38
+ "enabled:hover:bg-gray-3",
39
+ "enabled:hover:transition-[background-color]",
40
+ "enabled:hover:ease-in",
41
+ "enabled:hover:duration-150",
42
+ "focus-ring-outside",
43
+ "[--focus-ring-offset:-2px]",
44
+ "ring-gray-12"
45
+ ], className)
46
+ };
47
+ return useRender({
48
+ render,
49
+ defaultTagName: "button",
50
+ props: mergeProps(baseProps, rest)
51
+ });
52
+ };
53
+ DataTableHeaderButton.displayName = "DataTable.HeaderButton";
54
+ //#endregion
55
+ export { DataTableHeaderButton };
56
+
57
+ //# sourceMappingURL=data-table-header-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-header-button.js","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-button.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\n\nexport type DataTableHeaderButtonProps = useRender.ComponentProps<'button'>;\n\n/**\n * O botão do tamanho da célula do header, sem ação: a base do `DataTable.SortTrigger` e de outros\n * gatilhos do header, como o de um popover da coluna. Ocupa a `DataTable.HeaderCell` inteira; nas\n * bordas, a área de agarre do `DataTable.ResizeHandle` fica por cima. Alinha o conteúdo pelo\n * `data-align` da `DataTable.HeaderCell`, sem precisar do header.\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger render={<DataTable.HeaderButton />}>\n * <DataTable.HeaderContent header={header} />\n * </Popover.Trigger>\n * …\n * </Popover.Root>\n * ```\n */\nexport const DataTableHeaderButton = (props: DataTableHeaderButtonProps) => {\n const { render, className, ...rest } = props;\n\n const baseProps = {\n 'data-component': 'DataTable.HeaderButton',\n // Só no `button` padrão: com `render`, o elemento é de quem passou, como o `span` do\n // `DataTable.SortTrigger` numa coluna que não ordena.\n type: render === undefined ? 'button' : undefined,\n className: mergeTwClassNames(\n [\n // A célula inteira, com um padding só: sai do padding da `DataTable.HeaderCell` pela\n // margem negativa e põe o mesmo por dentro. O texto fica na linha do texto das células,\n // em qualquer densidade.\n 'flex-1',\n 'self-stretch',\n 'min-w-0',\n '-mx-(--data-table-cell-padding)',\n 'px-(--data-table-cell-padding)',\n\n 'flex',\n 'items-center',\n 'gap-1',\n // Pelo `data-align` da `DataTable.HeaderCell`. `end`, e não o `flex-end` do\n // `justify-end`: segue o fim da linha mesmo com a ordem invertida (`flex-row-reverse`).\n 'in-data-[align=center]:justify-center',\n 'in-data-[align=end]:[justify-content:end]',\n\n // O `text-align: center` do botão centralizaria o texto truncado.\n 'text-start',\n\n // `:enabled` só casa com o botão: um `span` fica de fora. O fundo do hover sobe um passo do\n // `gray-2` do cabeçalho, a mesma cor do hover da linha; o texto não muda. A transição só\n // durante o hover, como no `Button` do `ui`.\n 'enabled:cursor-pointer',\n 'enabled:hover:bg-gray-3',\n 'enabled:hover:transition-[background-color]',\n 'enabled:hover:ease-in',\n 'enabled:hover:duration-150',\n\n // Por dentro: a célula vizinha pinta depois e cobriria um anel por fora.\n 'focus-ring-outside',\n '[--focus-ring-offset:-2px]',\n 'ring-gray-12',\n ],\n className,\n ),\n };\n\n return useRender({\n render,\n defaultTagName: 'button',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableHeaderButton.displayName = 'DataTable.HeaderButton';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,MAAa,yBAAyB,UAAsC;CAC1E,MAAM,EAAE,QAAQ,WAAW,GAAG,SAAS;CAEvC,MAAM,YAAY;EAChB,kBAAkB;EAGlB,MAAM,WAAW,KAAA,IAAY,WAAW,KAAA;EACxC,WAAW,kBACT;GAIE;GACA;GACA;GACA;GACA;GAEA;GACA;GACA;GAGA;GACA;GAGA;GAKA;GACA;GACA;GACA;GACA;GAGA;GACA;GACA;EACF,GACA,SACF;CACF;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,sBAAsB,cAAc"}
@@ -0,0 +1,34 @@
1
+ import { Header, RowData, TableFeatures } from "@tanstack/react-table";
2
+ import { useRender } from "@base-ui/react";
3
+ import { MergeOverride } from "@lucasbernardosn/utils";
4
+ //#region src/components/data-table/header/data-table-header-cell.d.ts
5
+ export type DataTableHeaderCellProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'div'>, {
6
+ /** O header da coluna. */
7
+ header: Header<TFeatures, TData>;
8
+ }>;
9
+ /**
10
+ * A célula de um header (`role="columnheader"`). Num header de grupo, ocupa as colunas que o
11
+ * grupo abrange; num placeholder, fica vazia e marcada com `data-placeholder`.
12
+ *
13
+ * Com `rowSortingFeature`, marca a direção da ordenação em `aria-sort` e `data-sorted`. Com
14
+ * `columnAlignmentFeature`, alinha o conteúdo pelo `align` da coluna e o marca em `data-align`.
15
+ * Com `columnPinningFeature`, num header fixado, gruda na borda do lado dele, marcado com
16
+ * `data-pinned`.
17
+ *
18
+ * Sem `children`, mostra o `DataTable.HeaderContent`. Com eles, monte o conteúdo, o
19
+ * `DataTable.HeaderContent` incluso, e o `DataTable.ResizeHandle`, que se ancora na borda daqui.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * <DataTable.HeaderCell header={header}>
24
+ * <DataTable.HeaderContent header={header} />
25
+ * <DataTable.ResizeHandle header={header} />
26
+ * </DataTable.HeaderCell>
27
+ * ```
28
+ */
29
+ export declare const DataTableHeaderCell: {
30
+ <TFeatures extends TableFeatures, TData extends RowData>(props: DataTableHeaderCellProps<TFeatures, TData>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
31
+ displayName: string;
32
+ };
33
+ //#endregion
34
+ //# sourceMappingURL=data-table-header-cell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-header-cell.d.ts","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-cell.tsx"],"mappings":";;;;YAYY,yBACV,kBAAkB,eAClB,cAAc,WACZ,cACF,UAAU;;EAGR,QAAQ,OAAO,WAAW;;;;;;;;;;;;;;;;;;;;;;qBAwBjB;GACX,kBAAkB,eAClB,cAAc,SAAO,OAEd,yBAAyB,WAAW,yBAAM,+CAAA"}
@@ -0,0 +1,97 @@
1
+ import { hasColumnFeature, hasHeaderFeature } from "../../../utils/has-feature.js";
2
+ import { getDataTableColumnPinning, getDataTablePinnedStyle } from "../root/get-data-table-column-pinning.js";
3
+ import { DataTableHeaderContent } from "./data-table-header-content.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+ import { mergeProps, useRender } from "@base-ui/react";
6
+ import { useSelector } from "@tanstack/react-store";
7
+ import { mergeTwClassNames } from "@lucasbernardosn/react-ui/utils";
8
+ //#region src/components/data-table/header/data-table-header-cell.tsx
9
+ /**
10
+ * A célula de um header (`role="columnheader"`). Num header de grupo, ocupa as colunas que o
11
+ * grupo abrange; num placeholder, fica vazia e marcada com `data-placeholder`.
12
+ *
13
+ * Com `rowSortingFeature`, marca a direção da ordenação em `aria-sort` e `data-sorted`. Com
14
+ * `columnAlignmentFeature`, alinha o conteúdo pelo `align` da coluna e o marca em `data-align`.
15
+ * Com `columnPinningFeature`, num header fixado, gruda na borda do lado dele, marcado com
16
+ * `data-pinned`.
17
+ *
18
+ * Sem `children`, mostra o `DataTable.HeaderContent`. Com eles, monte o conteúdo, o
19
+ * `DataTable.HeaderContent` incluso, e o `DataTable.ResizeHandle`, que se ancora na borda daqui.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * <DataTable.HeaderCell header={header}>
24
+ * <DataTable.HeaderContent header={header} />
25
+ * <DataTable.ResizeHandle header={header} />
26
+ * </DataTable.HeaderCell>
27
+ * ```
28
+ */
29
+ const DataTableHeaderCell = (props) => {
30
+ const { header, render, className, children, ...rest } = props;
31
+ /**
32
+ * Só re-renderiza quando a ordenação desta coluna muda. A ordenação é opcional, então assina o
33
+ * store, e o guard estreita o header; sem `rowSortingFeature`, fica `false`.
34
+ */
35
+ const sorted = useSelector(header.column.table.store, () => hasHeaderFeature(header, "rowSortingFeature") ? header.column.getIsSorted() : false);
36
+ /**
37
+ * Sem assinatura: o alinhamento vem da definição da coluna, que não muda em runtime. Num grupo,
38
+ * é o da definição do grupo.
39
+ */
40
+ const align = hasColumnFeature(header.column, "columnAlignmentFeature") ? header.column.getAlign() : void 0;
41
+ /**
42
+ * A fixação vem da coluna folha da ponta: a primeira, no início, e a última, no fim, com o
43
+ * deslocamento dela. Num grupo, o `getIsPinned()` diz fixado se qualquer folha for, e só a folha
44
+ * da ponta sabe o lado e o lugar. Sem assinatura: o pinning muda os grupos, e o
45
+ * `DataTable.Header` re-renderiza, com o header junto.
46
+ */
47
+ const leafHeaders = header.getLeafHeaders().filter((leafHeader) => leafHeader.subHeaders.length === 0);
48
+ const startPinning = getDataTableColumnPinning((leafHeaders.at(0) ?? header).column);
49
+ const pinning = startPinning.position === "start" ? startPinning : getDataTableColumnPinning((leafHeaders.at(-1) ?? header).column);
50
+ const isGroup = header.colSpan > 1;
51
+ const baseProps = {
52
+ "data-component": "DataTable.HeaderCell",
53
+ "data-placeholder": header.isPlaceholder ? "" : void 0,
54
+ "data-sorted": sorted || void 0,
55
+ "data-align": align,
56
+ "data-pinned": pinning.position || void 0,
57
+ role: "columnheader",
58
+ "aria-sort": sorted === "asc" ? "ascending" : sorted === "desc" ? "descending" : void 0,
59
+ "aria-colspan": isGroup ? header.colSpan : void 0,
60
+ style: {
61
+ gridColumn: isGroup ? `span ${header.colSpan}` : void 0,
62
+ ...getDataTablePinnedStyle(pinning)
63
+ },
64
+ className: mergeTwClassNames([
65
+ "relative",
66
+ "flex",
67
+ "items-center",
68
+ "gap-1",
69
+ "data-[align=center]:justify-center",
70
+ "data-[align=end]:justify-end",
71
+ "min-w-0",
72
+ "h-(--data-table-header-height)",
73
+ "px-(--data-table-cell-padding)",
74
+ "data-pinned:sticky",
75
+ "data-pinned:z-20",
76
+ "data-[pinned=start]:has-[+:not([data-pinned=start])]:shadow-[6px_0_8px_-6px_rgb(0_0_0/0.12)]",
77
+ "dark:data-[pinned=start]:has-[+:not([data-pinned=start])]:shadow-[6px_0_8px_-6px_rgb(0_0_0/0.8)]",
78
+ "data-[pinned=end]:not-[[data-pinned=end]+*]:shadow-[-6px_0_8px_-6px_rgb(0_0_0/0.12)]",
79
+ "dark:data-[pinned=end]:not-[[data-pinned=end]+*]:shadow-[-6px_0_8px_-6px_rgb(0_0_0/0.8)]",
80
+ "bg-gray-2",
81
+ "text-xs",
82
+ "font-medium",
83
+ "text-gray-11"
84
+ ], className),
85
+ children: children === void 0 ? /* @__PURE__ */ jsx(DataTableHeaderContent, { header }) : children
86
+ };
87
+ return useRender({
88
+ render,
89
+ defaultTagName: "div",
90
+ props: mergeProps(baseProps, rest)
91
+ });
92
+ };
93
+ DataTableHeaderCell.displayName = "DataTable.HeaderCell";
94
+ //#endregion
95
+ export { DataTableHeaderCell };
96
+
97
+ //# sourceMappingURL=data-table-header-cell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-header-cell.js","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-cell.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport { useSelector } from '@tanstack/react-store';\nimport type { Header, RowData, TableFeatures } from '@tanstack/react-table';\nimport { hasColumnFeature, hasHeaderFeature } from '../../../utils';\nimport {\n getDataTableColumnPinning,\n getDataTablePinnedStyle,\n} from '../root/get-data-table-column-pinning';\nimport { DataTableHeaderContent } from './data-table-header-content';\n\nexport type DataTableHeaderCellProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'div'>,\n {\n /** O header da coluna. */\n header: Header<TFeatures, TData>;\n }\n>;\n\n/**\n * A célula de um header (`role=\"columnheader\"`). Num header de grupo, ocupa as colunas que o\n * grupo abrange; num placeholder, fica vazia e marcada com `data-placeholder`.\n *\n * Com `rowSortingFeature`, marca a direção da ordenação em `aria-sort` e `data-sorted`. Com\n * `columnAlignmentFeature`, alinha o conteúdo pelo `align` da coluna e o marca em `data-align`.\n * Com `columnPinningFeature`, num header fixado, gruda na borda do lado dele, marcado com\n * `data-pinned`.\n *\n * Sem `children`, mostra o `DataTable.HeaderContent`. Com eles, monte o conteúdo, o\n * `DataTable.HeaderContent` incluso, e o `DataTable.ResizeHandle`, que se ancora na borda daqui.\n *\n * @example\n * ```tsx\n * <DataTable.HeaderCell header={header}>\n * <DataTable.HeaderContent header={header} />\n * <DataTable.ResizeHandle header={header} />\n * </DataTable.HeaderCell>\n * ```\n */\nexport const DataTableHeaderCell = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableHeaderCellProps<TFeatures, TData>,\n) => {\n const { header, render, className, children, ...rest } = props;\n\n /**\n * Só re-renderiza quando a ordenação desta coluna muda. A ordenação é opcional, então assina o\n * store, e o guard estreita o header; sem `rowSortingFeature`, fica `false`.\n */\n const sorted = useSelector(header.column.table.store, () =>\n hasHeaderFeature(header, 'rowSortingFeature')\n ? header.column.getIsSorted()\n : false,\n );\n\n /**\n * Sem assinatura: o alinhamento vem da definição da coluna, que não muda em runtime. Num grupo,\n * é o da definição do grupo.\n */\n const align = hasColumnFeature(header.column, 'columnAlignmentFeature')\n ? header.column.getAlign()\n : undefined;\n\n /**\n * A fixação vem da coluna folha da ponta: a primeira, no início, e a última, no fim, com o\n * deslocamento dela. Num grupo, o `getIsPinned()` diz fixado se qualquer folha for, e só a folha\n * da ponta sabe o lado e o lugar. Sem assinatura: o pinning muda os grupos, e o\n * `DataTable.Header` re-renderiza, com o header junto.\n */\n const leafHeaders = header\n .getLeafHeaders()\n .filter((leafHeader) => leafHeader.subHeaders.length === 0);\n const startPinning = getDataTableColumnPinning(\n (leafHeaders.at(0) ?? header).column,\n );\n const pinning =\n startPinning.position === 'start'\n ? startPinning\n : getDataTableColumnPinning((leafHeaders.at(-1) ?? header).column);\n\n const isGroup = header.colSpan > 1;\n\n const baseProps = {\n 'data-component': 'DataTable.HeaderCell',\n 'data-placeholder': header.isPlaceholder ? '' : undefined,\n 'data-sorted': sorted || undefined,\n 'data-align': align,\n 'data-pinned': pinning.position || undefined,\n role: 'columnheader',\n 'aria-sort':\n sorted === 'asc'\n ? 'ascending'\n : sorted === 'desc'\n ? 'descending'\n : undefined,\n 'aria-colspan': isGroup ? header.colSpan : undefined,\n style: {\n // Os tracks do grid são os das colunas folha: o grupo abrange os das colunas dele.\n gridColumn: isGroup ? `span ${header.colSpan}` : undefined,\n ...getDataTablePinnedStyle(pinning),\n },\n className: mergeTwClassNames(\n [\n // O `DataTable.ResizeHandle` se posiciona por aqui.\n 'relative',\n\n 'flex',\n 'items-center',\n 'gap-1',\n // Vale para o conteúdo solto. O `DataTable.HeaderButton` ocupa a célula e segue o\n // `data-align` daqui por conta própria.\n 'data-[align=center]:justify-center',\n 'data-[align=end]:justify-end',\n\n // Item de grid tem `min-width: auto`: sem isto, um conteúdo longo alarga o track, e a\n // coluna deixa de bater com o template. Sem `overflow-hidden`: quem trunca é o\n // `DataTable.HeaderContent`, e o recorte aqui cortaria a área de agarre do handle.\n 'min-w-0',\n\n // Do `DataTable.Root`, pela densidade.\n 'h-(--data-table-header-height)',\n\n 'px-(--data-table-cell-padding)',\n\n // Fixado: gruda acima dos handles de resize das colunas do centro (`z-10`), que passam por\n // baixo dele.\n 'data-pinned:sticky',\n 'data-pinned:z-20',\n // A sombra na borda da fixada, como na `DataTable.Cell`.\n 'data-[pinned=start]:has-[+:not([data-pinned=start])]:shadow-[6px_0_8px_-6px_rgb(0_0_0/0.12)]',\n 'dark:data-[pinned=start]:has-[+:not([data-pinned=start])]:shadow-[6px_0_8px_-6px_rgb(0_0_0/0.8)]',\n 'data-[pinned=end]:not-[[data-pinned=end]+*]:shadow-[-6px_0_8px_-6px_rgb(0_0_0/0.12)]',\n 'dark:data-[pinned=end]:not-[[data-pinned=end]+*]:shadow-[-6px_0_8px_-6px_rgb(0_0_0/0.8)]',\n\n // Opaco: o cabeçalho gruda, e as linhas passam por baixo; fixado, o centro também.\n 'bg-gray-2',\n\n 'text-xs',\n 'font-medium',\n 'text-gray-11',\n ],\n className,\n ),\n children:\n children === undefined ? (\n <DataTableHeaderContent header={header} />\n ) : (\n children\n ),\n };\n\n return useRender({\n render,\n defaultTagName: 'div',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableHeaderCell.displayName = 'DataTable.HeaderCell';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAa,uBAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,UAAU,GAAG,SAAS;;;;;CAMzD,MAAM,SAAS,YAAY,OAAO,OAAO,MAAM,aAC7C,iBAAiB,QAAQ,mBAAmB,IACxC,OAAO,OAAO,YAAY,IAC1B,KACN;;;;;CAMA,MAAM,QAAQ,iBAAiB,OAAO,QAAQ,wBAAwB,IAClE,OAAO,OAAO,SAAS,IACvB,KAAA;;;;;;;CAQJ,MAAM,cAAc,OACjB,eAAe,CAAC,CAChB,QAAQ,eAAe,WAAW,WAAW,WAAW,CAAC;CAC5D,MAAM,eAAe,2BAClB,YAAY,GAAG,CAAC,KAAK,OAAA,CAAQ,MAChC;CACA,MAAM,UACJ,aAAa,aAAa,UACtB,eACA,2BAA2B,YAAY,GAAG,EAAE,KAAK,OAAA,CAAQ,MAAM;CAErE,MAAM,UAAU,OAAO,UAAU;CAEjC,MAAM,YAAY;EAChB,kBAAkB;EAClB,oBAAoB,OAAO,gBAAgB,KAAK,KAAA;EAChD,eAAe,UAAU,KAAA;EACzB,cAAc;EACd,eAAe,QAAQ,YAAY,KAAA;EACnC,MAAM;EACN,aACE,WAAW,QACP,cACA,WAAW,SACT,eACA,KAAA;EACR,gBAAgB,UAAU,OAAO,UAAU,KAAA;EAC3C,OAAO;GAEL,YAAY,UAAU,QAAQ,OAAO,YAAY,KAAA;GACjD,GAAG,wBAAwB,OAAO;EACpC;EACA,WAAW,kBACT;GAEE;GAEA;GACA;GACA;GAGA;GACA;GAKA;GAGA;GAEA;GAIA;GACA;GAEA;GACA;GACA;GACA;GAGA;GAEA;GACA;GACA;EACF,GACA,SACF;EACA,UACE,aAAa,KAAA,IACX,oBAAC,wBAAD,EAAgC,OAAS,CAAA,IAEzC;CAEN;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,oBAAoB,cAAc"}
@@ -0,0 +1,21 @@
1
+ import { Header, RowData, TableFeatures } from "@tanstack/react-table";
2
+ import { useRender } from "@base-ui/react";
3
+ import { MergeOverride } from "@lucasbernardosn/utils";
4
+ //#region src/components/data-table/header/data-table-header-content.d.ts
5
+ export type DataTableHeaderContentProps<TFeatures extends TableFeatures, TData extends RowData> = MergeOverride<useRender.ComponentProps<'span'>, {
6
+ /** O header da coluna. */
7
+ header: Header<TFeatures, TData>;
8
+ }>;
9
+ /**
10
+ * O conteúdo do header: o `header` da definição da coluna, truncado com reticências. Num header
11
+ * placeholder, fica vazio. Com `children`, eles substituem o da definição.
12
+ *
13
+ * Existe à parte porque o `DataTable.HeaderCell` não pode recortar: a área de agarre do
14
+ * `DataTable.ResizeHandle` passa da borda dele, e conteúdo recortado não recebe clique.
15
+ */
16
+ export declare const DataTableHeaderContent: {
17
+ <TFeatures extends TableFeatures, TData extends RowData>(props: DataTableHeaderContentProps<TFeatures, TData>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
18
+ displayName: string;
19
+ };
20
+ //#endregion
21
+ //# sourceMappingURL=data-table-header-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-header-content.d.ts","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-content.tsx"],"mappings":";;;;YAUY,4BACV,kBAAkB,eAClB,cAAc,WACZ,cACF,UAAU;;EAGR,QAAQ,OAAO,WAAW;;;;;;;;;qBAWjB;GACX,kBAAkB,eAClB,cAAc,SAAO,OAEd,4BAA4B,WAAW,yBAAM,+CAAA"}
@@ -0,0 +1,37 @@
1
+ import { FlexRender } from "@tanstack/react-table";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { mergeProps, useRender } from "@base-ui/react";
4
+ import { mergeTwClassNames } from "@lucasbernardosn/react-ui/utils";
5
+ //#region src/components/data-table/header/data-table-header-content.tsx
6
+ /**
7
+ * O conteúdo do header: o `header` da definição da coluna, truncado com reticências. Num header
8
+ * placeholder, fica vazio. Com `children`, eles substituem o da definição.
9
+ *
10
+ * Existe à parte porque o `DataTable.HeaderCell` não pode recortar: a área de agarre do
11
+ * `DataTable.ResizeHandle` passa da borda dele, e conteúdo recortado não recebe clique.
12
+ */
13
+ const DataTableHeaderContent = (props) => {
14
+ const { header, render, className, children, ...rest } = props;
15
+ const content = header.isPlaceholder ? null : /* @__PURE__ */ jsx(FlexRender, { header });
16
+ const baseProps = {
17
+ "data-component": "DataTable.HeaderContent",
18
+ className: mergeTwClassNames([
19
+ "block",
20
+ "min-w-0",
21
+ "truncate",
22
+ "-m-1",
23
+ "p-1"
24
+ ], className),
25
+ children: children === void 0 ? content : children
26
+ };
27
+ return useRender({
28
+ render,
29
+ defaultTagName: "span",
30
+ props: mergeProps(baseProps, rest)
31
+ });
32
+ };
33
+ DataTableHeaderContent.displayName = "DataTable.HeaderContent";
34
+ //#endregion
35
+ export { DataTableHeaderContent };
36
+
37
+ //# sourceMappingURL=data-table-header-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-header-content.js","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-content.tsx"],"sourcesContent":["import { mergeProps, useRender } from '@base-ui/react';\nimport { mergeTwClassNames } from '@lucasbernardosn/react-ui/utils';\nimport type { MergeOverride } from '@lucasbernardosn/utils';\nimport {\n FlexRender,\n type Header,\n type RowData,\n type TableFeatures,\n} from '@tanstack/react-table';\n\nexport type DataTableHeaderContentProps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = MergeOverride<\n useRender.ComponentProps<'span'>,\n {\n /** O header da coluna. */\n header: Header<TFeatures, TData>;\n }\n>;\n\n/**\n * O conteúdo do header: o `header` da definição da coluna, truncado com reticências. Num header\n * placeholder, fica vazio. Com `children`, eles substituem o da definição.\n *\n * Existe à parte porque o `DataTable.HeaderCell` não pode recortar: a área de agarre do\n * `DataTable.ResizeHandle` passa da borda dele, e conteúdo recortado não recebe clique.\n */\nexport const DataTableHeaderContent = <\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n props: DataTableHeaderContentProps<TFeatures, TData>,\n) => {\n const { header, render, className, children, ...rest } = props;\n\n const content = header.isPlaceholder ? null : <FlexRender header={header} />;\n\n const baseProps = {\n 'data-component': 'DataTable.HeaderContent',\n className: mergeTwClassNames(\n [\n // `span` em bloco: trunca como um bloco e ainda cabe num botão, que só aceita conteúdo\n // inline.\n 'block',\n 'min-w-0',\n 'truncate',\n\n // Afasta a borda do recorte 4px sem mover o conteúdo: cabe o anel de foco de um\n // controle aqui dentro, como o \"selecionar tudo\".\n '-m-1',\n 'p-1',\n ],\n className,\n ),\n children: children === undefined ? content : children,\n };\n\n return useRender({\n render,\n defaultTagName: 'span',\n props: mergeProps(baseProps, rest),\n });\n};\n\nDataTableHeaderContent.displayName = 'DataTable.HeaderContent';\n"],"mappings":";;;;;;;;;;;;AA4BA,MAAa,0BAIX,UACG;CACH,MAAM,EAAE,QAAQ,QAAQ,WAAW,UAAU,GAAG,SAAS;CAEzD,MAAM,UAAU,OAAO,gBAAgB,OAAO,oBAAC,YAAD,EAAoB,OAAS,CAAA;CAE3E,MAAM,YAAY;EAChB,kBAAkB;EAClB,WAAW,kBACT;GAGE;GACA;GACA;GAIA;GACA;EACF,GACA,SACF;EACA,UAAU,aAAa,KAAA,IAAY,UAAU;CAC/C;CAEA,OAAO,UAAU;EACf;EACA,gBAAgB;EAChB,OAAO,WAAW,WAAW,IAAI;CACnC,CAAC;AACH;AAEA,uBAAuB,cAAc"}
@@ -0,0 +1,15 @@
1
+ import { useRender } from "@base-ui/react";
2
+ //#region src/components/data-table/header/data-table-header-row.d.ts
3
+ export type DataTableHeaderRowProps = useRender.ComponentProps<'div'>;
4
+ /**
5
+ * Uma linha de headers (`role="row"`), por grupo de headers. É um grid com as colunas do
6
+ * `--data-table-template`, que o `DataTable.Root` escreve.
7
+ *
8
+ * O `DataTable.Header` com render-prop já monta uma por grupo; use direto só no laço feito à mão.
9
+ */
10
+ export declare const DataTableHeaderRow: {
11
+ (props: DataTableHeaderRowProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
12
+ displayName: string;
13
+ };
14
+ //#endregion
15
+ //# sourceMappingURL=data-table-header-row.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-header-row.d.ts","names":[],"sources":["../../../../src/components/data-table/header/data-table-header-row.tsx"],"mappings":";;YAIY,0BAA0B,UAAU;;;;;;;qBAQnC;GAA6B,OAAA,0CAAuB,+CAAA"}