@sincpro/web-ui 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 (354) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -2
  3. package/dist/components/assist/AssistMark.d.ts +64 -0
  4. package/dist/components/assist/AssistMark.js +108 -0
  5. package/dist/components/assist/AssistPending.d.ts +24 -0
  6. package/dist/components/assist/AssistPending.js +26 -0
  7. package/dist/components/assist/AssistSuggestion.d.ts +42 -0
  8. package/dist/components/assist/AssistSuggestion.js +55 -0
  9. package/dist/components/assist/ChangeReview.d.ts +56 -0
  10. package/dist/components/assist/ChangeReview.js +121 -0
  11. package/dist/components/assist/assist.d.ts +77 -0
  12. package/dist/components/assist/assist.js +87 -0
  13. package/dist/components/assist/index.d.ts +5 -0
  14. package/dist/components/assist/index.js +7 -0
  15. package/dist/components/chatter/Chatter.d.ts +161 -0
  16. package/dist/components/chatter/Chatter.js +232 -0
  17. package/dist/components/chatter/Messages.d.ts +66 -0
  18. package/dist/components/chatter/Messages.js +43 -0
  19. package/dist/components/chatter/Timeline.d.ts +21 -0
  20. package/dist/components/chatter/Timeline.js +30 -0
  21. package/dist/components/chatter/index.d.ts +3 -0
  22. package/dist/components/chatter/index.js +4 -0
  23. package/dist/components/form/Form.d.ts +52 -0
  24. package/dist/components/form/Form.js +49 -0
  25. package/dist/components/form/Sheet.d.ts +43 -0
  26. package/dist/components/form/Sheet.js +83 -0
  27. package/dist/components/form/index.d.ts +2 -0
  28. package/dist/components/form/index.js +4 -0
  29. package/dist/components/frame/Chart.d.ts +13 -0
  30. package/dist/components/frame/Chart.js +24 -0
  31. package/dist/components/frame/FrameView.d.ts +33 -0
  32. package/dist/components/frame/FrameView.js +125 -0
  33. package/dist/components/frame/index.d.ts +3 -0
  34. package/dist/components/frame/index.js +3 -0
  35. package/dist/components/frame/model.d.ts +43 -0
  36. package/dist/components/frame/model.js +101 -0
  37. package/dist/components/index.d.ts +10 -0
  38. package/dist/components/index.js +11 -0
  39. package/dist/components/lines/LineItems.d.ts +74 -0
  40. package/dist/components/lines/LineItems.js +229 -0
  41. package/dist/components/lines/index.d.ts +1 -0
  42. package/dist/components/lines/index.js +2 -0
  43. package/dist/components/lines/lines.d.ts +23 -0
  44. package/dist/components/lines/lines.js +26 -0
  45. package/dist/components/listing/ColumnsMenu.d.ts +20 -0
  46. package/dist/components/listing/ColumnsMenu.js +46 -0
  47. package/dist/components/listing/GroupingLevels.d.ts +35 -0
  48. package/dist/components/listing/GroupingLevels.js +45 -0
  49. package/dist/components/listing/Listing.d.ts +27 -0
  50. package/dist/components/listing/Listing.js +86 -0
  51. package/dist/components/listing/ListingBar.d.ts +73 -0
  52. package/dist/components/listing/ListingBar.js +105 -0
  53. package/dist/components/listing/Pagination.d.ts +36 -0
  54. package/dist/components/listing/Pagination.js +69 -0
  55. package/dist/components/listing/RecordCard.d.ts +33 -0
  56. package/dist/components/listing/RecordCard.js +22 -0
  57. package/dist/components/listing/RecordLink.d.ts +7 -0
  58. package/dist/components/listing/RecordLink.js +22 -0
  59. package/dist/components/listing/Row.d.ts +106 -0
  60. package/dist/components/listing/Row.js +122 -0
  61. package/dist/components/listing/SortMenu.d.ts +62 -0
  62. package/dist/components/listing/SortMenu.js +105 -0
  63. package/dist/components/listing/ViewSwitcher.d.ts +24 -0
  64. package/dist/components/listing/ViewSwitcher.js +16 -0
  65. package/dist/components/listing/columns.d.ts +47 -0
  66. package/dist/components/listing/columns.js +72 -0
  67. package/dist/components/listing/grouping.d.ts +35 -0
  68. package/dist/components/listing/grouping.js +47 -0
  69. package/dist/components/listing/index.d.ts +17 -0
  70. package/dist/components/listing/index.js +20 -0
  71. package/dist/components/listing/modelColumns.d.ts +50 -0
  72. package/dist/components/listing/modelColumns.js +103 -0
  73. package/dist/components/listing/pages.d.ts +78 -0
  74. package/dist/components/listing/pages.js +135 -0
  75. package/dist/components/listing/selection.d.ts +21 -0
  76. package/dist/components/listing/selection.js +43 -0
  77. package/dist/components/listing/set.d.ts +48 -0
  78. package/dist/components/listing/set.js +24 -0
  79. package/dist/components/listing/tree.d.ts +28 -0
  80. package/dist/components/listing/tree.js +23 -0
  81. package/dist/components/navigation/CommandPalette.d.ts +40 -0
  82. package/dist/components/navigation/CommandPalette.js +114 -0
  83. package/dist/components/navigation/NavigationTree.d.ts +31 -0
  84. package/dist/components/navigation/NavigationTree.js +79 -0
  85. package/dist/components/navigation/commands.d.ts +30 -0
  86. package/dist/components/navigation/commands.js +30 -0
  87. package/dist/components/navigation/index.d.ts +3 -0
  88. package/dist/components/navigation/index.js +4 -0
  89. package/dist/components/record/Breadcrumb.d.ts +42 -0
  90. package/dist/components/record/Breadcrumb.js +98 -0
  91. package/dist/components/record/DirtyActions.d.ts +26 -0
  92. package/dist/components/record/DirtyActions.js +22 -0
  93. package/dist/components/record/Pager.d.ts +18 -0
  94. package/dist/components/record/Pager.js +33 -0
  95. package/dist/components/record/RecordHeader.d.ts +71 -0
  96. package/dist/components/record/RecordHeader.js +72 -0
  97. package/dist/components/record/RecordSkeleton.d.ts +3 -0
  98. package/dist/components/record/RecordSkeleton.js +21 -0
  99. package/dist/components/record/SmartButtons.d.ts +35 -0
  100. package/dist/components/record/SmartButtons.js +38 -0
  101. package/dist/components/record/StatusBar.d.ts +51 -0
  102. package/dist/components/record/StatusBar.js +168 -0
  103. package/dist/components/record/ThumbBar.d.ts +36 -0
  104. package/dist/components/record/ThumbBar.js +86 -0
  105. package/dist/components/record/index.d.ts +6 -0
  106. package/dist/components/record/index.js +8 -0
  107. package/dist/components/search/CriteriaBuilder.d.ts +58 -0
  108. package/dist/components/search/CriteriaBuilder.js +278 -0
  109. package/dist/components/search/CriteriaChips.d.ts +22 -0
  110. package/dist/components/search/CriteriaChips.js +64 -0
  111. package/dist/components/search/FilterBuilder.d.ts +142 -0
  112. package/dist/components/search/FilterBuilder.js +421 -0
  113. package/dist/components/search/JoinWord.d.ts +8 -0
  114. package/dist/components/search/JoinWord.js +47 -0
  115. package/dist/components/search/JsonEditor.d.ts +19 -0
  116. package/dist/components/search/JsonEditor.js +78 -0
  117. package/dist/components/search/SearchBar.d.ts +78 -0
  118. package/dist/components/search/SearchBar.js +387 -0
  119. package/dist/components/search/criteria.d.ts +116 -0
  120. package/dist/components/search/criteria.js +159 -0
  121. package/dist/components/search/datePeriods.d.ts +122 -0
  122. package/dist/components/search/datePeriods.js +134 -0
  123. package/dist/components/search/dateRanges.d.ts +54 -0
  124. package/dist/components/search/dateRanges.js +89 -0
  125. package/dist/components/search/index.d.ts +9 -0
  126. package/dist/components/search/index.js +20 -0
  127. package/dist/components/search/model.d.ts +54 -0
  128. package/dist/components/search/model.js +37 -0
  129. package/dist/components/search/query.d.ts +166 -0
  130. package/dist/components/search/query.js +436 -0
  131. package/dist/components/shell/AppFrame.d.ts +14 -0
  132. package/dist/components/shell/AppFrame.js +80 -0
  133. package/dist/components/shell/TopBar.d.ts +73 -0
  134. package/dist/components/shell/TopBar.js +54 -0
  135. package/dist/components/shell/headerSlot.d.ts +17 -0
  136. package/dist/components/shell/headerSlot.js +21 -0
  137. package/dist/components/shell/index.d.ts +2 -0
  138. package/dist/components/shell/index.js +3 -0
  139. package/dist/foundations/aria.d.ts +14 -0
  140. package/dist/foundations/aria.js +18 -0
  141. package/dist/foundations/calendar.d.ts +28 -0
  142. package/dist/foundations/calendar.js +183 -0
  143. package/dist/foundations/copy.d.ts +619 -0
  144. package/dist/foundations/copy.es.d.ts +2 -0
  145. package/dist/foundations/copy.es.js +377 -0
  146. package/dist/foundations/copy.js +472 -0
  147. package/dist/foundations/density.d.ts +16 -0
  148. package/dist/foundations/density.js +21 -0
  149. package/dist/foundations/grouping.d.ts +281 -0
  150. package/dist/foundations/grouping.js +0 -0
  151. package/dist/foundations/index.d.ts +14 -0
  152. package/dist/foundations/index.js +30 -0
  153. package/dist/foundations/layout.d.ts +9 -0
  154. package/dist/foundations/layout.js +9 -0
  155. package/dist/foundations/pivot.d.ts +222 -0
  156. package/dist/foundations/pivot.js +198 -0
  157. package/dist/foundations/pivotSheet.d.ts +61 -0
  158. package/dist/foundations/pivotSheet.js +0 -0
  159. package/dist/foundations/slots.d.ts +67 -0
  160. package/dist/foundations/slots.js +63 -0
  161. package/dist/foundations/sticky.d.ts +53 -0
  162. package/dist/foundations/sticky.js +150 -0
  163. package/dist/foundations/surface.d.ts +9 -0
  164. package/dist/foundations/surface.js +26 -0
  165. package/dist/foundations/theme.d.ts +42 -0
  166. package/dist/foundations/theme.js +88 -0
  167. package/dist/foundations/types.d.ts +23 -0
  168. package/dist/foundations/types.js +50 -0
  169. package/dist/foundations/variants.d.ts +19 -0
  170. package/dist/foundations/variants.js +48 -0
  171. package/dist/foundations/xlsx.d.ts +86 -0
  172. package/dist/foundations/xlsx.js +0 -0
  173. package/dist/index.d.ts +19 -0
  174. package/dist/index.js +19 -0
  175. package/dist/primitives/block/Block.d.ts +66 -0
  176. package/dist/primitives/block/Block.js +34 -0
  177. package/dist/primitives/block/Line.d.ts +18 -0
  178. package/dist/primitives/block/Line.js +45 -0
  179. package/dist/primitives/block/SectionGrid.d.ts +30 -0
  180. package/dist/primitives/block/SectionGrid.js +29 -0
  181. package/dist/primitives/block/Steps.d.ts +76 -0
  182. package/dist/primitives/block/Steps.js +43 -0
  183. package/dist/primitives/block/index.d.ts +4 -0
  184. package/dist/primitives/block/index.js +7 -0
  185. package/dist/primitives/button/Button.d.ts +137 -0
  186. package/dist/primitives/button/Button.js +234 -0
  187. package/dist/primitives/button/index.d.ts +1 -0
  188. package/dist/primitives/button/index.js +2 -0
  189. package/dist/primitives/cell/CellStack.d.ts +47 -0
  190. package/dist/primitives/cell/CellStack.js +33 -0
  191. package/dist/primitives/cell/index.d.ts +1 -0
  192. package/dist/primitives/cell/index.js +3 -0
  193. package/dist/primitives/choice/ComboBox.d.ts +16 -0
  194. package/dist/primitives/choice/ComboBox.js +52 -0
  195. package/dist/primitives/choice/RadioGroup.d.ts +18 -0
  196. package/dist/primitives/choice/RadioGroup.js +50 -0
  197. package/dist/primitives/choice/SearchField.d.ts +24 -0
  198. package/dist/primitives/choice/SearchField.js +27 -0
  199. package/dist/primitives/choice/SegmentedControl.d.ts +16 -0
  200. package/dist/primitives/choice/SegmentedControl.js +69 -0
  201. package/dist/primitives/choice/Slider.d.ts +16 -0
  202. package/dist/primitives/choice/Slider.js +46 -0
  203. package/dist/primitives/choice/Switch.d.ts +14 -0
  204. package/dist/primitives/choice/Switch.js +65 -0
  205. package/dist/primitives/choice/ThemeSwitcher.d.ts +10 -0
  206. package/dist/primitives/choice/ThemeSwitcher.js +25 -0
  207. package/dist/primitives/choice/index.d.ts +8 -0
  208. package/dist/primitives/choice/index.js +11 -0
  209. package/dist/primitives/choice/options.d.ts +28 -0
  210. package/dist/primitives/choice/options.js +6 -0
  211. package/dist/primitives/date/Calendar.d.ts +31 -0
  212. package/dist/primitives/date/Calendar.js +110 -0
  213. package/dist/primitives/date/DatePicker.d.ts +34 -0
  214. package/dist/primitives/date/DatePicker.js +99 -0
  215. package/dist/primitives/date/index.d.ts +2 -0
  216. package/dist/primitives/date/index.js +4 -0
  217. package/dist/primitives/dialog/Dialog.d.ts +118 -0
  218. package/dist/primitives/dialog/Dialog.js +121 -0
  219. package/dist/primitives/dialog/index.d.ts +1 -0
  220. package/dist/primitives/dialog/index.js +2 -0
  221. package/dist/primitives/disclosure/Disclosure.d.ts +36 -0
  222. package/dist/primitives/disclosure/Disclosure.js +52 -0
  223. package/dist/primitives/disclosure/index.d.ts +1 -0
  224. package/dist/primitives/disclosure/index.js +2 -0
  225. package/dist/primitives/field/Checks.d.ts +57 -0
  226. package/dist/primitives/field/Checks.js +72 -0
  227. package/dist/primitives/field/DropZone.d.ts +42 -0
  228. package/dist/primitives/field/DropZone.js +52 -0
  229. package/dist/primitives/field/Field.d.ts +166 -0
  230. package/dist/primitives/field/Field.js +240 -0
  231. package/dist/primitives/field/Suggest.d.ts +48 -0
  232. package/dist/primitives/field/Suggest.js +43 -0
  233. package/dist/primitives/field/aria.d.ts +61 -0
  234. package/dist/primitives/field/aria.js +70 -0
  235. package/dist/primitives/field/context.d.ts +30 -0
  236. package/dist/primitives/field/context.js +13 -0
  237. package/dist/primitives/field/index.d.ts +7 -0
  238. package/dist/primitives/field/index.js +11 -0
  239. package/dist/primitives/field/layout.d.ts +24 -0
  240. package/dist/primitives/field/layout.js +10 -0
  241. package/dist/primitives/field/mode.d.ts +9 -0
  242. package/dist/primitives/field/mode.js +13 -0
  243. package/dist/primitives/hint/Hint.d.ts +31 -0
  244. package/dist/primitives/hint/Hint.js +42 -0
  245. package/dist/primitives/hint/index.d.ts +1 -0
  246. package/dist/primitives/hint/index.js +1 -0
  247. package/dist/primitives/index.d.ts +19 -0
  248. package/dist/primitives/index.js +20 -0
  249. package/dist/primitives/menu/Menu.d.ts +100 -0
  250. package/dist/primitives/menu/Menu.js +59 -0
  251. package/dist/primitives/menu/index.d.ts +1 -0
  252. package/dist/primitives/menu/index.js +2 -0
  253. package/dist/primitives/notice/Callout.d.ts +49 -0
  254. package/dist/primitives/notice/Callout.js +28 -0
  255. package/dist/primitives/notice/Notice.d.ts +45 -0
  256. package/dist/primitives/notice/Notice.js +61 -0
  257. package/dist/primitives/notice/Toast.d.ts +55 -0
  258. package/dist/primitives/notice/Toast.js +142 -0
  259. package/dist/primitives/notice/index.d.ts +3 -0
  260. package/dist/primitives/notice/index.js +5 -0
  261. package/dist/primitives/overlay/Popover.d.ts +6 -0
  262. package/dist/primitives/overlay/Popover.js +27 -0
  263. package/dist/primitives/overlay/PopoverTrigger.d.ts +55 -0
  264. package/dist/primitives/overlay/PopoverTrigger.js +38 -0
  265. package/dist/primitives/overlay/Tooltip.d.ts +38 -0
  266. package/dist/primitives/overlay/Tooltip.js +74 -0
  267. package/dist/primitives/overlay/index.d.ts +3 -0
  268. package/dist/primitives/overlay/index.js +5 -0
  269. package/dist/primitives/picker/Picker.d.ts +48 -0
  270. package/dist/primitives/picker/Picker.js +150 -0
  271. package/dist/primitives/picker/index.d.ts +1 -0
  272. package/dist/primitives/picker/index.js +2 -0
  273. package/dist/primitives/surface/Peek.d.ts +60 -0
  274. package/dist/primitives/surface/Peek.js +71 -0
  275. package/dist/primitives/surface/index.d.ts +1 -0
  276. package/dist/primitives/surface/index.js +2 -0
  277. package/dist/primitives/table/CellEditor.d.ts +14 -0
  278. package/dist/primitives/table/CellEditor.js +83 -0
  279. package/dist/primitives/table/DataTable.d.ts +135 -0
  280. package/dist/primitives/table/DataTable.js +244 -0
  281. package/dist/primitives/table/EditableTable.d.ts +96 -0
  282. package/dist/primitives/table/EditableTable.js +423 -0
  283. package/dist/primitives/table/PivotTable.d.ts +14 -0
  284. package/dist/primitives/table/PivotTable.js +0 -0
  285. package/dist/primitives/table/ReportTable.d.ts +38 -0
  286. package/dist/primitives/table/ReportTable.js +106 -0
  287. package/dist/primitives/table/RowActions.d.ts +16 -0
  288. package/dist/primitives/table/RowActions.js +28 -0
  289. package/dist/primitives/table/SheetTable.d.ts +70 -0
  290. package/dist/primitives/table/SheetTable.js +197 -0
  291. package/dist/primitives/table/Table.d.ts +106 -0
  292. package/dist/primitives/table/Table.js +116 -0
  293. package/dist/primitives/table/index.d.ts +7 -0
  294. package/dist/primitives/table/index.js +9 -0
  295. package/dist/primitives/tabs/Tabs.d.ts +91 -0
  296. package/dist/primitives/tabs/Tabs.js +56 -0
  297. package/dist/primitives/tabs/index.d.ts +1 -0
  298. package/dist/primitives/tabs/index.js +1 -0
  299. package/dist/primitives/tag/Tag.d.ts +36 -0
  300. package/dist/primitives/tag/Tag.js +68 -0
  301. package/dist/primitives/tag/Tags.d.ts +57 -0
  302. package/dist/primitives/tag/Tags.js +104 -0
  303. package/dist/primitives/tag/TagsField.d.ts +32 -0
  304. package/dist/primitives/tag/TagsField.js +182 -0
  305. package/dist/primitives/tag/choices.d.ts +38 -0
  306. package/dist/primitives/tag/choices.js +26 -0
  307. package/dist/primitives/tag/index.d.ts +4 -0
  308. package/dist/primitives/tag/index.js +8 -0
  309. package/dist/primitives/toolbar/Toolbar.d.ts +13 -0
  310. package/dist/primitives/toolbar/Toolbar.js +36 -0
  311. package/dist/primitives/toolbar/index.d.ts +1 -0
  312. package/dist/primitives/toolbar/index.js +2 -0
  313. package/dist/primitives/value/Copyable.d.ts +37 -0
  314. package/dist/primitives/value/Copyable.js +50 -0
  315. package/dist/primitives/value/Fecha.d.ts +12 -0
  316. package/dist/primitives/value/Fecha.js +80 -0
  317. package/dist/primitives/value/Meter.d.ts +29 -0
  318. package/dist/primitives/value/Meter.js +46 -0
  319. package/dist/primitives/value/Metric.d.ts +42 -0
  320. package/dist/primitives/value/Metric.js +38 -0
  321. package/dist/primitives/value/Person.d.ts +90 -0
  322. package/dist/primitives/value/Person.js +208 -0
  323. package/dist/primitives/value/Relation.d.ts +69 -0
  324. package/dist/primitives/value/Relation.js +57 -0
  325. package/dist/primitives/value/Totals.d.ts +26 -0
  326. package/dist/primitives/value/Totals.js +4 -0
  327. package/dist/primitives/value/Value.d.ts +77 -0
  328. package/dist/primitives/value/Value.js +119 -0
  329. package/dist/primitives/value/index.d.ts +8 -0
  330. package/dist/primitives/value/index.js +9 -0
  331. package/dist/tokens.css +1025 -0
  332. package/dist/views/index.d.ts +2 -0
  333. package/dist/views/index.js +3 -0
  334. package/dist/views/list/List.d.ts +113 -0
  335. package/dist/views/list/List.js +97 -0
  336. package/dist/views/list/ListView.d.ts +6 -0
  337. package/dist/views/list/ListView.js +269 -0
  338. package/dist/views/list/columns.d.ts +18 -0
  339. package/dist/views/list/columns.js +27 -0
  340. package/dist/views/list/derive.d.ts +76 -0
  341. package/dist/views/list/derive.js +181 -0
  342. package/dist/views/list/index.d.ts +2 -0
  343. package/dist/views/list/index.js +4 -0
  344. package/dist/views/list/presentations.d.ts +39 -0
  345. package/dist/views/list/presentations.js +103 -0
  346. package/dist/views/list/types.d.ts +272 -0
  347. package/dist/views/list/types.js +1 -0
  348. package/dist/views/list/useNarrowList.d.ts +17 -0
  349. package/dist/views/list/useNarrowList.js +32 -0
  350. package/dist/views/record/Record.d.ts +126 -0
  351. package/dist/views/record/Record.js +141 -0
  352. package/dist/views/record/index.d.ts +1 -0
  353. package/dist/views/record/index.js +2 -0
  354. package/package.json +109 -4
@@ -0,0 +1,135 @@
1
+ import type { Tone } from "../../foundations/types.js";
2
+ import { type RowAction } from "./RowActions.js";
3
+ import { type SortState } from "./Table.js";
4
+ import { type ReactNode } from "react";
5
+ /** How a column is aggregated when its rows are pulled together into a group.
6
+ *
7
+ * **`count` is the default and it is the right one almost always**: summing
8
+ * identifiers or averaging file sizes produces numbers that look like data and
9
+ * mean nothing. An aggregate has to be chosen on purpose. */
10
+ export type Aggregate = "count" | "sum" | "mean" | "min" | "max" | "unique";
11
+ export interface DataColumn<T> {
12
+ id: string;
13
+ header: string;
14
+ /** Qué campo del MODELO muestra esta columna, cuando no se llama igual que
15
+ * él: «filas» muestra `row_count`. Lo lee `columnsFromModel` para no volver
16
+ * a agregar, en crudo, un campo que esta columna ya contesta. */
17
+ field?: string;
18
+ /** The raw value: this is what sorting and grouping run on. */
19
+ value: (row: T) => string | number | boolean | null;
20
+ /** How it is drawn. Without this the raw value is drawn. */
21
+ cell?: (row: T) => ReactNode;
22
+ /** A column of CODES — a SKU, a hash, a key — set in the monospaced face. Numbers do not
23
+ * need it: they align with tabular figures in the same face as the rest of the row. */
24
+ mono?: boolean;
25
+ /**
26
+ * Cómo se LEE la columna donde no se puede dibujar: la planilla, que es una
27
+ * cuadrícula de texto y números y no puede recibir un nodo.
28
+ *
29
+ * Context: sin esto, la planilla caía a `value`, que es la clave de ORDEN y
30
+ * no lo que una persona lee. La columna «estado» de Facturas mostraba
31
+ * `posted` y `paid` —los valores del contrato— en vez de «publicada» y
32
+ * «pagada», que es lo que dice la ficha de al lado en la tabla. Dos
33
+ * presentaciones del mismo conjunto diciendo cosas distintas.
34
+ */
35
+ text?: (row: T) => string;
36
+ /** Paints the BACKGROUND of the cell, row by row. It is what turns a table
37
+ * into something you look at: «this amount is out of range», «this value was
38
+ * imputed by the engine». Returning `undefined` leaves the cell unpainted,
39
+ * which is the normal case — a table with everything colored highlights
40
+ * nothing. */
41
+ tone?: (row: T) => Tone | undefined;
42
+ /** Why it is painted, on hover. */
43
+ note?: (row: T) => string | undefined;
44
+ numeric?: boolean;
45
+ width?: number;
46
+ aggregate?: Aggregate;
47
+ sortable?: boolean;
48
+ /** Odoo: fields without `optional` cannot leave the view. When true, the
49
+ * column appears in the columns submenu and can be hidden. */
50
+ optional?: boolean;
51
+ /** Odoo `optional="hide"`: start off. Only with `optional`. */
52
+ defaultHidden?: boolean;
53
+ /**
54
+ * Edit this cell IN the list, through a small popover anchored to it: the salesperson of
55
+ * an invoice, its due date, its stage. The cell becomes a button (with a pencil on hover
56
+ * and focus) and `render` draws the editor inside the popover.
57
+ *
58
+ * Context: one function and not a kind of editor, because the editor is the system's own
59
+ * control — a `Picker`, a `Calendar`, a `Select` — written by whoever knows the field.
60
+ * The editor commits with its own gesture and then calls `done`, which closes the popover
61
+ * and returns the focus to the cell. Escape and a click outside close without committing.
62
+ * Do not draw links in an editable column: the cell is already a button.
63
+ */
64
+ edit?: {
65
+ render: (row: T, done: () => void) => ReactNode;
66
+ /** Which rows can be changed — a paid invoice cannot. All of them by default. */
67
+ when?: (row: T) => boolean;
68
+ };
69
+ }
70
+ /**
71
+ * El agregado de una columna sobre un conjunto de filas.
72
+ *
73
+ * Vive afuera del componente porque lo preguntan tres lugares: el pie de la
74
+ * tabla, la banda de un montón en la planilla, y la línea de un informe armado
75
+ * a partir de los montones. Tres implementaciones de «cuánto suma esto» es que
76
+ * el pie diga un número y el montón otro.
77
+ *
78
+ * `null` cuando la columna no declaró agregado, no es numérica, o no hay ningún
79
+ * número que sumar — que es distinto de sumar cero.
80
+ */
81
+ export declare function aggregateOf<T extends object>(column: DataColumn<T>, rows: readonly T[]): number | null;
82
+ /**
83
+ * UN NIVEL, como lo necesita una tabla.
84
+ *
85
+ * La identidad es la del NIVEL y no la del campo: un mismo `registered_at`
86
+ * puesto por mes y por día son dos cortes, y con el nombre del campo serían el
87
+ * mismo repetido. `keyOf` da la clave del motor —la misma que arman las otras
88
+ * presentaciones, así que lo plegado vale para todas— y `labelOf` la lee en el
89
+ * idioma activo.
90
+ */
91
+ export type GroupColumn<T> = {
92
+ /** La identidad del nivel: `levelKey(level)`. */
93
+ id: string;
94
+ /** Cómo se llama el corte, a la izquierda del valor. Sin él, «Septiembre» no
95
+ * dice si es cuándo se registró o cuándo se corrió. */
96
+ label: string;
97
+ /** A qué montón va cada fila en este nivel. */
98
+ keyOf: (item: T) => string;
99
+ /** Cómo se lee esa clave. */
100
+ labelOf: (key: string) => string;
101
+ };
102
+ export declare function DataTable<T extends object>({ data, columns, getRowId, sort, onSortChange, levels, selected, onSelectedChange, height, onRowClick, rowActions, totals, collapsed, onGroupToggle, }: {
103
+ data: readonly T[];
104
+ columns: readonly DataColumn<T>[];
105
+ getRowId: (row: T) => string;
106
+ sort?: SortState | null;
107
+ onSortChange?: (next: SortState | null) => void;
108
+ /**
109
+ * Los NIVELES por los que se parte, de afuera hacia adentro. Vacío o ausente
110
+ * es «sin agrupar».
111
+ *
112
+ * Varios, porque agrupar no es una pregunta: «por cliente y después por
113
+ * mes» es un árbol y no una lista de montones. El orden ES la jerarquía.
114
+ */
115
+ levels?: readonly GroupColumn<T>[];
116
+ selected?: ReadonlySet<string>;
117
+ onSelectedChange?: (next: Set<string>) => void;
118
+ height?: number;
119
+ onRowClick?: (row: T) => void;
120
+ /** What you do to ONE row without going into it. They are drawn hidden and
121
+ * show up on the hovered row — see `RowActions.tsx`. */
122
+ rowActions?: (row: T) => readonly RowAction[];
123
+ /** The footer with the aggregate of every column that declared one.
124
+ *
125
+ * Context: up to now the aggregate only existed INSIDE a group, so an
126
+ * ungrouped table had no way to say how much it adds up to — and «how much
127
+ * does it add up to» is the question that makes a table of amounts a report
128
+ * and not a list. It stays pinned at the bottom: in a four-hundred-row table,
129
+ * a total you have to scroll to is a total nobody sees. */
130
+ totals?: boolean;
131
+ /** Group keys that are closed. Same keys as `ListGroup.collapsed`, so the
132
+ * table does not reopen what rows just folded. */
133
+ collapsed?: readonly string[];
134
+ onGroupToggle?: (key: string) => void;
135
+ }): import("react").JSX.Element;
@@ -0,0 +1,244 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { fillCopy, useUiCopy } from "../../foundations/copy.js";
4
+ import { pathKey } from "../../foundations/grouping.js";
5
+ import { CellEditor } from "./CellEditor.js";
6
+ import { RowActions } from "./RowActions.js";
7
+ import { SelectBox, Table, Td, Th, THead, Tr, } from "./Table.js";
8
+ import { aggregationFns, columnGroupingFeature, createColumnHelper, createExpandedRowModel, createGroupedRowModel, createSortedRowModel, rowAggregationFeature, rowExpandingFeature, rowSortingFeature, sortFns, tableFeatures, useTable, } from "@tanstack/react-table";
9
+ import { ChevronRight } from "lucide-react";
10
+ import { useMemo } from "react";
11
+ function aggregateLabel(copy, kind, v) {
12
+ const n = v.toLocaleString(copy.locale);
13
+ switch (kind) {
14
+ case "sum":
15
+ return n;
16
+ case "count":
17
+ return `${n} ${v === 1 ? copy.table.row : copy.table.rows}`;
18
+ case "mean":
19
+ return fillCopy(copy.table.mean, {
20
+ value: v.toLocaleString(copy.locale, { maximumFractionDigits: 2 }),
21
+ });
22
+ case "min":
23
+ return fillCopy(copy.table.min, { value: n });
24
+ case "max":
25
+ return fillCopy(copy.table.max, { value: n });
26
+ case "unique":
27
+ return fillCopy(copy.table.distinct, { value: n });
28
+ }
29
+ }
30
+ function raw(copy, v) {
31
+ if (v === null)
32
+ return "—";
33
+ if (typeof v === "number")
34
+ return v.toLocaleString(copy.locale);
35
+ if (typeof v === "boolean")
36
+ return v ? copy.table.yes : copy.table.no;
37
+ return v;
38
+ }
39
+ /** What a cell draws: its `cell`, or the raw value. */
40
+ function drawCell(copy, column, row) {
41
+ return column.cell === undefined ? raw(copy, column.value(row)) : column.cell(row);
42
+ }
43
+ /* The features are declared once. In v9 they are opt-in: asking only for what
44
+ is used is what keeps the bundle down to what is actually needed. */
45
+ const FEATURES = tableFeatures({
46
+ rowSortingFeature,
47
+ columnGroupingFeature,
48
+ rowExpandingFeature,
49
+ // `rowAggregationFeature` is what enables `aggregationFn` on a column.
50
+ // Without it, grouping pulls rows together but each column does not know what
51
+ // to show in the group row — which is half of the reason for grouping.
52
+ rowAggregationFeature,
53
+ sortedRowModel: createSortedRowModel(),
54
+ groupedRowModel: createGroupedRowModel(),
55
+ expandedRowModel: createExpandedRowModel(),
56
+ sortFns,
57
+ aggregationFns,
58
+ });
59
+ /**
60
+ * El agregado de una columna sobre un conjunto de filas.
61
+ *
62
+ * Vive afuera del componente porque lo preguntan tres lugares: el pie de la
63
+ * tabla, la banda de un montón en la planilla, y la línea de un informe armado
64
+ * a partir de los montones. Tres implementaciones de «cuánto suma esto» es que
65
+ * el pie diga un número y el montón otro.
66
+ *
67
+ * `null` cuando la columna no declaró agregado, no es numérica, o no hay ningún
68
+ * número que sumar — que es distinto de sumar cero.
69
+ */
70
+ export function aggregateOf(column, rows) {
71
+ if (column.aggregate === undefined || column.numeric !== true)
72
+ return null;
73
+ const numbers = rows
74
+ .map((row) => column.value(row))
75
+ .filter((value) => typeof value === "number");
76
+ if (numbers.length === 0)
77
+ return null;
78
+ switch (column.aggregate) {
79
+ case "sum":
80
+ return numbers.reduce((a, b) => a + b, 0);
81
+ case "mean":
82
+ return numbers.reduce((a, b) => a + b, 0) / numbers.length;
83
+ case "min":
84
+ return Math.min(...numbers);
85
+ case "max":
86
+ return Math.max(...numbers);
87
+ case "unique":
88
+ return new Set(numbers).size;
89
+ default:
90
+ return numbers.length;
91
+ }
92
+ }
93
+ export function DataTable({ data, columns, getRowId, sort, onSortChange, levels, selected, onSelectedChange, height, onRowClick, rowActions, totals = false, collapsed, onGroupToggle, }) {
94
+ const copy = useUiCopy();
95
+ // In v9 the helper is bound to the features AND to the data type: that is what
96
+ // makes the compiler know about `enableGrouping` only if we ask for the
97
+ // feature.
98
+ const helper = useMemo(() => createColumnHelper(), []);
99
+ const defs = useMemo(() => [
100
+ ...columns.map((c) => helper.accessor((row) => c.value(row), {
101
+ id: c.id,
102
+ header: c.header,
103
+ enableSorting: c.sortable !== false,
104
+ /* Ninguna columna agrupa. Lo que parte el conjunto son los NIVELES, y
105
+ cada uno entra como una columna suya —abajo— que existe sólo para
106
+ eso: nadie la dibuja y nadie la ordena. */
107
+ enableGrouping: false,
108
+ aggregationFn: c.aggregate ?? "count",
109
+ })),
110
+ /* Una columna por NIVEL, no por campo. Es la única forma de que «por mes y
111
+ adentro por día» sea dos cortes: con el id de la columna, los dos niveles
112
+ de `registered_at` eran el mismo id repetido, y un mismo id no se puede
113
+ agrupar dos veces.
114
+
115
+ Y la clave la pone el nivel, no la columna: `value` es la clave de
116
+ ORDEN —para una fecha, los milisegundos— y agrupar por ella deja un
117
+ montón por instante, con «1789294903895» de rótulo. Acá entra la misma
118
+ clave que arman las otras cinco presentaciones, así que los montones de
119
+ la tabla son LOS MISMOS y lo plegado vale para todas. */
120
+ ...(levels ?? []).map((level) => helper.accessor((row) => level.keyOf(row), {
121
+ id: level.id,
122
+ header: level.label,
123
+ enableSorting: false,
124
+ enableGrouping: true,
125
+ })),
126
+ ], [columns, helper, levels]);
127
+ /* The assertion, and why it is safe: `ColumnDef` is INVARIANT in its value
128
+ type (`in out TValue`), so an array of columns with concrete values is not
129
+ assignable to the one of `unknown` even though each one on its own is. The
130
+ library solves this with `helper.columns([...])`, which needs a literal
131
+ tuple — and here the columns come out of a `map` over what the consumer
132
+ declared, which is not literal.
133
+
134
+ It is safe because that value is only used by the library to sort and
135
+ group; it is never read with its type from our side. What gets drawn comes
136
+ from `c.cell(row)` or from `c.value(row)`, both typed against `T`. */
137
+ const table = useTable({
138
+ features: FEATURES,
139
+ data,
140
+ columns: defs,
141
+ getRowId: (row) => getRowId(row),
142
+ state: {
143
+ sorting: sort === null || sort === undefined
144
+ ? []
145
+ : [{ id: sort.key, desc: sort.direction === "desc" }],
146
+ grouping: (levels ?? []).map((level) => level.id),
147
+ },
148
+ // Groups start open: grouping and then having to open each group is two
149
+ // gestures for what the user asked for in one.
150
+ initialState: { expanded: true },
151
+ });
152
+ const rows = table.getRowModel().rows;
153
+ /**
154
+ * The PATH of a row: the values of every group it hangs from, outermost
155
+ * first.
156
+ *
157
+ * The identity of a pile is its route and not its value, because with several
158
+ * levels two piles can be called the same — «2026-09» inside «Ferretería Sur» and
159
+ * «2026-09» inside «Distribuidora Andina» are different piles, and folding one must not
160
+ * fold the other. It walks up because that is where TanStack keeps the
161
+ * ancestry; a leaf contributes nothing, since `groupingColumnId` is only set
162
+ * on grouped rows.
163
+ */
164
+ function pathOf(row) {
165
+ const path = [];
166
+ let node = row;
167
+ while (node !== undefined) {
168
+ const columnId = node.groupingColumnId;
169
+ if (columnId !== undefined && columnId !== null) {
170
+ path.unshift(String(node.getGroupingValue(columnId) ?? "—"));
171
+ }
172
+ node = node.getParentRow();
173
+ }
174
+ return path;
175
+ }
176
+ /* TanStack keeps every leaf in the model when `expanded: true`. Folding is
177
+ ours: the same path keys as the rows presentation, so switching present
178
+ does not reopen a group.
179
+
180
+ It checks EVERY ancestor and not just the parent. With one level they were
181
+ the same thing; with several, folding the outer pile has to take the inner
182
+ ones with it — otherwise closing «Ferretería Sur» leaves its months on screen,
183
+ orphaned under a header that says it is closed. */
184
+ const drawn = collapsed === undefined
185
+ ? rows
186
+ : rows.filter((row) => {
187
+ let node = row.getParentRow();
188
+ while (node !== undefined) {
189
+ if (collapsed.includes(pathKey(pathOf(node))))
190
+ return false;
191
+ node = node.getParentRow();
192
+ }
193
+ return true;
194
+ });
195
+ const selecting = onSelectedChange !== undefined;
196
+ const leaves = useMemo(() => rows.filter((r) => r.subRows.length === 0), [rows]);
197
+ /* The aggregates are computed by the component and not by TanStack: its
198
+ `aggregationFn` lives in the GROUP model, and a footer exists precisely when
199
+ there are no groups. */
200
+ const footer = useMemo(() => (totals ? columns.map((c) => aggregateOf(c, data)) : null), [totals, columns, data]);
201
+ const all = leaves.length > 0 && leaves.every((r) => selected?.has(r.id) === true);
202
+ const some = leaves.some((r) => selected?.has(r.id) === true);
203
+ function toggle(id, on) {
204
+ const n = new Set(selected ?? []);
205
+ if (on)
206
+ n.add(id);
207
+ else
208
+ n.delete(id);
209
+ onSelectedChange?.(n);
210
+ }
211
+ return (_jsxs(Table, { height: height, children: [_jsxs(THead, { children: [selecting ? (_jsx(Th, { width: 36, children: _jsx(SelectBox, { label: copy.selection.all, checked: all, indeterminate: some, onChange: (v) => onSelectedChange?.(v ? new Set(leaves.map((r) => r.id)) : new Set()) }) })) : null, columns.map((c) => (_jsx(Th, { sortKey: c.sortable === false ? undefined : c.id, sort: sort, onSort: onSortChange, numeric: c.numeric, width: c.width, children: c.header }, c.id))), rowActions === undefined ? null : _jsx(Th, { width: 1, children: "" })] }), _jsx("tbody", { children: drawn.map((row) => {
212
+ const isGroup = row.subRows.length > 0;
213
+ if (isGroup) {
214
+ const path = pathOf(row);
215
+ const key = pathKey(path);
216
+ const depth = path.length - 1;
217
+ const id = row.groupingColumnId ?? undefined;
218
+ const level = levels?.find((one) => one.id === id);
219
+ /* La CLAVE del montón —la del motor— y el rótulo, que lo pone el
220
+ nivel: son dos textos y sólo el segundo cambia con el idioma. */
221
+ const value = path[depth] ?? key;
222
+ const open = collapsed === undefined
223
+ ? row.getIsExpanded()
224
+ : collapsed.includes(key) !== true;
225
+ return (
226
+ /* The group row: it spans the whole width, says which value it
227
+ groups by and how many are inside. The counter is what makes it
228
+ useful without opening it. */
229
+ _jsx("tr", { className: "border-b border-line bg-ground", children: _jsx("td", { colSpan: columns.length + (selecting ? 1 : 0) + (rowActions === undefined ? 0 : 1), className: "px-3 py-1.5", style: depth === 0
230
+ ? undefined
231
+ : { paddingLeft: `calc(var(--spacing-indent) * ${depth} + 0.75rem)` }, children: _jsxs("button", { type: "button", onClick: () => onGroupToggle === undefined ? row.toggleExpanded() : onGroupToggle(key), "aria-expanded": open, className: "inline-flex items-center gap-1.5 rounded-control text-meta font-medium text-ink transition-colors duration-(--duration-instant) hover:text-primary focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-primary", children: [_jsx(ChevronRight, { className: `size-(--size-icon-sm) text-muted transition-transform duration-(--duration-instant) ${open ? "rotate-90" : ""}`, strokeWidth: 2, "aria-hidden": true }), level === undefined ? null : (_jsx("span", { className: "text-micro font-normal text-muted/70", children: level.label })), _jsx("span", { children: level === undefined ? value : level.labelOf(value) }), _jsx("span", { className: "inline-flex shrink-0 items-center rounded-pill border border-line-strong bg-ink/5 px-2 py-0.5 text-micro tabular-nums text-muted", children: row.getLeafRows().length.toLocaleString(copy.locale) })] }) }) }, row.id));
232
+ }
233
+ const original = row.original;
234
+ return (_jsxs(Tr, { selected: selected?.has(row.id) === true, onClick: onRowClick === undefined ? undefined : () => onRowClick(original), children: [selecting ? (_jsx(Td, { children: _jsx(SelectBox, { label: copy.selection.row, checked: selected?.has(row.id) === true, onChange: (v) => toggle(row.id, v) }) })) : null, columns.map((c) => {
235
+ const t = c.tone?.(original);
236
+ const n = c.note?.(original);
237
+ const edit = c.edit?.when?.(original) === false ? undefined : c.edit;
238
+ return (_jsx(Td, { numeric: c.numeric, mono: c.mono === true, ...(t === undefined ? {} : { tone: t }), ...(n === undefined ? {} : { title: n }), children: edit !== undefined ? (_jsx(CellEditor, { label: fillCopy(copy.inlineEdit.editCell, { column: c.header }), numeric: c.numeric === true, editor: (done) => edit.render(original, done), children: drawCell(copy, c, original) })) : (drawCell(copy, c, original)) }, c.id));
239
+ }), rowActions === undefined ? null : (_jsx(RowActions, { actions: rowActions(original) }))] }, row.id));
240
+ }) }), footer === null ? null : (_jsx("tfoot", { className: "sticky bottom-0 z-10 bg-ground", children: _jsxs("tr", { className: "border-t border-line-strong", children: [selecting ? _jsx("td", {}) : null, columns.map((c, i) => {
241
+ const value = footer[i] ?? null;
242
+ return (_jsx("td", { className: `px-3 py-1.5 text-meta font-semibold text-ink ${c.numeric === true ? "text-right tabular-nums" : ""}`, children: i === 0 && value === null ? (_jsxs("span", { className: "text-muted", children: [data.length.toLocaleString(copy.locale), " ", data.length === 1 ? copy.table.row : copy.table.rows] })) : value === null ? null : (aggregateLabel(copy, c.aggregate ?? "count", value)) }, c.id));
243
+ }), rowActions === undefined ? null : _jsx("td", {})] }) }))] }));
244
+ }
@@ -0,0 +1,96 @@
1
+ import { type Grouping } from "../../foundations/grouping.js";
2
+ import { type ReactNode } from "react";
3
+ /** Where a column goes when the row is drawn as a stacked card (a narrow box).
4
+ * `trail` sits at the top right, beside the title — a state, the row's buttons. */
5
+ export type StackPlace = "title" | "detail" | "amount" | "trail" | "hidden";
6
+ /** How the rows are drawn: `auto` measures the box and stacks them below
7
+ * `--container-handheld`; `table` and `stacked` force one — a side panel that is
8
+ * always narrow, a test that has no box to measure. */
9
+ export type EditLayout = "auto" | "table" | "stacked";
10
+ export interface EditColumn<T> {
11
+ id: string;
12
+ header: string;
13
+ width?: number;
14
+ numeric?: boolean;
15
+ /** How the cell reads when the row is NOT being edited. */
16
+ render: (row: T) => ReactNode;
17
+ /** The control, when the row is being edited. Without this the column is read
18
+ * only: an identifier or a computed value. Give the control an `aria-label`
19
+ * (the column's name, or a longer one): a cell has no `Field` to name it, and
20
+ * `Tab` through the row reads each control by that name. */
21
+ edit?: (row: T, set: (next: T) => void) => ReactNode;
22
+ /** Where the column goes in the stacked card, below `--container-handheld`. By
23
+ * default the first column is the `title`, the last numeric one the `amount` and
24
+ * the rest `detail`. `hidden` for what another column's `brief` already says. */
25
+ stack?: StackPlace;
26
+ /** How the column reads inside the card's detail line, when «header value» is not
27
+ * the way to say it: «12 × Bs. 120,00» for a quantity, «desc. 10 %» for a
28
+ * discount. `null` or `""` leaves it out of that row's line — a zero discount is
29
+ * not news. Without it the line reads «<header> <cell>». */
30
+ brief?: (row: T) => ReactNode;
31
+ }
32
+ /**
33
+ * Where each column goes in the stacked card, defaults resolved: a declared `stack`
34
+ * wins; otherwise the first undeclared column is the title (unless one was declared),
35
+ * the last undeclared numeric one is the amount (unless one was declared), and the rest
36
+ * are detail.
37
+ */
38
+ export declare function stackPlaces(columns: readonly {
39
+ stack?: StackPlace;
40
+ numeric?: boolean;
41
+ }[]): StackPlace[];
42
+ /**
43
+ * A table whose rows are edited in place, one row at a time.
44
+ *
45
+ * Mouse: touching a row opens it. Keyboard: the rows are one tab stop, the arrows walk
46
+ * them, `Enter` / `F2` open one, `Tab` walks its controls, `Enter` commits and `Escape`
47
+ * puts the row back as it was; both return the focus to the row. Leaving the row
48
+ * (click outside, tabbing past its last control) commits.
49
+ *
50
+ * Narrower than `--container-handheld`, each row is a stacked card (see the file's
51
+ * header): the same keys, and `onOpen` —when given— instead of editing in place.
52
+ */
53
+ export declare function EditableTable<T>({ rows, columns, getRowId, onChange, onRemove, onAdd, addLabel,
54
+ /** The footer with the aggregates, already formatted. `null` on the columns
55
+ * that do not add up. Whoever composes computes it, because whoever composes
56
+ * knows what adding up means in their domain —a percentage is not summed, it
57
+ * is averaged. */
58
+ totals, empty, grouping,
59
+ /** El total de una columna DENTRO de un montón, ya formateado. Lo calcula quien
60
+ * compone, por el mismo motivo que `totals`: sumar significa cosas distintas
61
+ * según el dominio, y un porcentaje se promedia, no se suma. */
62
+ groupTotal, height, layout, onOpen, }: {
63
+ rows: readonly T[];
64
+ columns: readonly EditColumn<T>[];
65
+ getRowId: (row: T) => string;
66
+ onChange?: (id: string, next: T) => void;
67
+ onRemove?: (id: string) => void;
68
+ onAdd?: () => void;
69
+ addLabel?: string;
70
+ totals?: readonly (ReactNode | null)[];
71
+ empty?: string;
72
+ /**
73
+ * El agrupado, con el mismo contrato que el resto de las vistas de datos.
74
+ *
75
+ * Editar y agrupar no se estorban: la fila que se edita sigue siendo una fila,
76
+ * y el montón sólo decide dónde cae. Lo que no se hereda es el orden — las
77
+ * filas de un montón quedan juntas, así que agregar una fila nueva la pone al
78
+ * final de todo y no adentro del montón que estabas mirando, que es el
79
+ * comportamiento honesto: todavía no tiene valor en el campo por el que se
80
+ * agrupa.
81
+ */
82
+ grouping?: Grouping<T>;
83
+ groupTotal?: (column: EditColumn<T>, rows: readonly T[]) => ReactNode | null;
84
+ /** A height of its own, as `Table`'s: the lines scroll inside the box and the header
85
+ * sticks to its top. A number means pixels; a string goes through as is (`20rem`).
86
+ * Without it the table grows with its lines and the header sticks to the page. */
87
+ height?: number | string;
88
+ /** `auto` (the default) stacks the rows as cards when the box is narrower than
89
+ * `--container-handheld`; `table` and `stacked` force one. */
90
+ layout?: EditLayout;
91
+ /** Only in the stacked layout: pressing a card (or `Enter` / `F2` on it) calls this
92
+ * instead of editing the row in place — for a consumer that edits the whole row in a
93
+ * form of its own, a dialog that is a bottom sheet on a phone. The table ignores it:
94
+ * there the row is edited where it is read. */
95
+ onOpen?: (id: string) => void;
96
+ }): import("react").JSX.Element;