@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,281 @@
1
+ /**
2
+ * LA AGRUPACIÓN, en N niveles.
3
+ *
4
+ * Context: agrupar es partir un conjunto por lo que sus filas comparten, y eso
5
+ * no tiene por qué ser UNA pregunta. «Por procedencia» es una; «por procedencia
6
+ * y después por mes» es la misma pregunta hecha dos veces, y la respuesta es un
7
+ * árbol y no una lista de montones.
8
+ *
9
+ * ── Qué se PIDE y qué se DIBUJA son dos cosas ──────────────────────
10
+ *
11
+ * `GroupLevel` es lo que alguien pidió: por qué campo partir y, si es una
12
+ * fecha, con qué grano. `Pile` es lo que se dibuja: un montón ya armado, con su
13
+ * rótulo, cuántas filas tiene y el nivel de abajo. Están separados porque los
14
+ * montones no siempre los arma esta máquina: los puede armar quien tenga los
15
+ * datos —y contar un catálogo entero es algo que sólo puede contestar quien lo
16
+ * guarda—. Por eso `pilesFrom` es un HELPER y no el único camino: una
17
+ * presentación recibe `piles` y no sabe ni le importa quién los contó.
18
+ *
19
+ * **Esto no conoce ningún motor.** Ni criteria, ni cursores, ni transporte: un
20
+ * montón acá es rótulo, conteo, hijos y filas. Quien traduzca la respuesta de un
21
+ * servidor a esta forma vive afuera, y por eso la misma presentación sirve para
22
+ * un agrupado hecho en el navegador y para uno contado a mil kilómetros.
23
+ *
24
+ * ── La identidad de un montón es su RUTA ────────────────────────────
25
+ *
26
+ * Y no su clave. Con un solo nivel alcanzaba la clave, porque no había dos
27
+ * montones que pudieran llamarse igual. Con N niveles sí: «2026-09» puede ser un
28
+ * mes adentro de «sintético» y otro adentro de «traído», y son montones
29
+ * distintos que se pliegan por separado. La ruta —`["sintético", "2026-09"]`—
30
+ * es lo único que los distingue, así que es lo que se guarda.
31
+ *
32
+ * ── La CLAVE identifica; el RÓTULO se lee ───────────────────────────
33
+ *
34
+ * Y son dos textos. «2026-09» es lo que el motor escribe: lo que se compara con
35
+ * lo que contó el servidor, lo que la ruta lleva, lo que queda plegado. Con eso
36
+ * a la vista la interfaz habla en máquina, así que el montón lleva además su
37
+ * rótulo —«Septiembre»— que es lo que se dibuja y lo único que cambia con el
38
+ * idioma. Al revés no se puede: con el rótulo por identidad, dos septiembres de
39
+ * años distintos se funden en un montón que no existe, y plegar un mes en
40
+ * español lo dejaría abierto en inglés.
41
+ *
42
+ * Para un campo que no es una fecha los dos textos son el mismo —«sintético» se
43
+ * identifica y se lee igual— y por eso el rótulo sólo se pone aparte donde hace
44
+ * falta: en las fechas, que las nombra `system/calendar.ts`.
45
+ */
46
+ /** El grano de un nivel de fecha. Sin grano, un campo de fecha parte por
47
+ * instante y cada fila termina en su propio montón, que es no agrupar. */
48
+ export type GroupGrain = "day" | "week" | "month" | "quarter" | "year";
49
+ /**
50
+ * De GRUESO a fino. Es el orden en que se anidan los granos de un mismo campo, y
51
+ * no es una preferencia: agrupar por día y después por mes daría montones de un
52
+ * día dentro de meses que ya no parten nada, porque un día entero vive adentro
53
+ * de un solo mes. La jerarquía de un calendario tiene una dirección y es ésta.
54
+ */
55
+ export declare const GRAIN_ORDER: readonly GroupGrain[];
56
+ /** Un NIVEL: por qué campo se parte, y con qué grano si es una fecha. Es lo que
57
+ * alguien pidió, no lo que se dibuja. */
58
+ export type GroupLevel = {
59
+ field: string;
60
+ grain?: GroupGrain;
61
+ };
62
+ /** Un campo por el que SE PUEDE agrupar, para que el control ofrezca algo. Los
63
+ * granos se declaran acá y no se adivinan del tipo: quién sabe si una fecha se
64
+ * mira por semana o por trimestre es el dominio, y ofrecer los cuatro siempre
65
+ * es ofrecer tres que a nadie le sirven. */
66
+ export type GroupableField = {
67
+ field: string;
68
+ label: string;
69
+ /** Presentes = es una fecha y estos son los cortes que tienen sentido. */
70
+ grains?: readonly GroupGrain[];
71
+ };
72
+ /**
73
+ * Un MONTÓN ya armado: lo que sus filas comparten, cuántas son, y el nivel de
74
+ * abajo.
75
+ */
76
+ export type Pile<T> = {
77
+ /** La ruta desde la raíz, en CLAVES. Es la identidad del montón: lo que lo
78
+ * pliega y lo que lo distingue de un hermano homónimo en otra rama. */
79
+ path: readonly string[];
80
+ /** Cuán adentro está. `0` es el primer nivel. Lo usa la sangría. */
81
+ depth: number;
82
+ /** Por qué campo se partió acá. Lo dibuja el encabezado a la izquierda del
83
+ * valor: sin él, «2026-09» no dice si es cuándo se registró o cuándo se
84
+ * corrió. */
85
+ field: string;
86
+ /** Lo que las filas COMPARTEN, en el idioma del motor: «2026-09». Es el último
87
+ * tramo de la ruta, y lo que se compara con lo que contó el servidor. */
88
+ key: string;
89
+ /** El mismo valor, ya legible y en el idioma activo: «Septiembre». Es lo que
90
+ * se dibuja, y lo único de un montón que cambia con el idioma. */
91
+ label: string;
92
+ /**
93
+ * Cuántas filas hay en el montón — TODAS, no las de la página.
94
+ *
95
+ * Es la diferencia entre «hay 187 sintéticos» y «se ven 12»: un conteo que
96
+ * cambia al pasar de página no es un conteo, es un largo de array. Cuando los
97
+ * montones los cuenta quien guarda los datos, este número viene de allá.
98
+ */
99
+ count: number;
100
+ /** Las filas, en el nivel MÁS PROFUNDO. Vacío en los de arriba: un montón que
101
+ * tiene montones adentro no tiene filas propias. */
102
+ items: readonly T[];
103
+ /** El nivel de abajo. Vacío en el más profundo. */
104
+ piles: readonly Pile<T>[];
105
+ };
106
+ /**
107
+ * La identidad de un NIVEL: el campo y, si es fecha, su grano.
108
+ *
109
+ * El campo solo no alcanza desde que un mismo campo puede estar puesto con
110
+ * varios granos —«por mes y adentro por día» son dos niveles del mismo
111
+ * `registered_at`— y dos niveles que se llaman igual no se pueden ni sacar ni
112
+ * mover por separado.
113
+ */
114
+ export declare function levelKey(level: GroupLevel): string;
115
+ /**
116
+ * Los niveles, acomodados.
117
+ *
118
+ * Dos reglas, y las dos son del calendario y no del gusto de nadie:
119
+ *
120
+ * 1. Los niveles de un MISMO campo quedan juntos. Partir por mes, después por
121
+ * procedencia y después por día del mismo campo deja dos cortes de la misma
122
+ * fecha separados por otra cosa, y eso no es una jerarquía, es un tropiezo.
123
+ * 2. Adentro de un campo van de GRUESO a FINO. Tildar «día» y después «mes»
124
+ * tiene que dar «mes › día», porque al revés el mes no parte nada: un día
125
+ * entero ya vive adentro de un solo mes.
126
+ *
127
+ * El orden ENTRE campos lo decide quien agrupa —es una pregunta del dominio, no
128
+ * del calendario— así que se respeta el de primera aparición y se puede mover.
129
+ */
130
+ export declare function normalizeLevels(levels: readonly GroupLevel[]): GroupLevel[];
131
+ /**
132
+ * LO QUE HACE AGRUPABLE A UNA VISTA.
133
+ *
134
+ * Cualquier componente que dibuje N cosas —filas, tarjetas, celdas, líneas de un
135
+ * informe, puntos de una serie— puede agrupar aceptando ESTO y nada más. Es
136
+ * deliberadamente corto: cinco campos, ninguno opcional por capricho.
137
+ *
138
+ * ── Lo que el contrato SÍ fija ──────────────────────────────────────
139
+ *
140
+ * levels qué se pregunta, y en qué orden
141
+ * of a qué montón va cada cosa, ya legible
142
+ * piles el árbol ya armado, si lo contó alguien con el conjunto entero
143
+ * collapsed qué está plegado, por ruta
144
+ * onToggle cómo se pliega
145
+ *
146
+ * ── Lo que NO fija, y es el punto ───────────────────────────────────
147
+ *
148
+ * **Cómo se dibuja un montón.** La lista pone un encabezado con filete; la
149
+ * planilla, una banda pegada a la izquierda porque está virtualizada por índice
150
+ * y no puede anidar el marcado; la tabla usa una fila con `colSpan`; el informe
151
+ * hace una línea con sus subtotales; una serie haría una serie por montón. Las
152
+ * cinco son correctas y ninguna sirve para las otras — un contrato que además
153
+ * dictara el dibujo obligaría a todas a parecerse a la primera que se escribió.
154
+ *
155
+ * Por eso lo que se comparte es el ÁRBOL y no el render: quien implementa recibe
156
+ * `Pile[]` de `pilesOf()` y lo recorre como su presentación necesite.
157
+ *
158
+ * ── Cómo se implementa ──────────────────────────────────────────────
159
+ *
160
+ * function MiVista<T>({ items, grouping }: { items: readonly T[]; grouping?: Grouping<T> }) {
161
+ * const piles = pilesOf(items, grouping);
162
+ * if (piles === null) return <>{items.map(dibujar)}</>;
163
+ * return recorrer(piles); // ← acá manda la presentación
164
+ * }
165
+ */
166
+ export type Grouping<T> = {
167
+ /**
168
+ * Los niveles pedidos, de afuera hacia adentro. Vacío = sin agrupar.
169
+ *
170
+ * El ORDEN es la jerarquía: `[origen, mes]` y `[mes, origen]` son dos lecturas
171
+ * distintas del mismo conjunto.
172
+ */
173
+ levels: readonly GroupLevel[];
174
+ /** A qué montón va cada cosa, en cada nivel: la CLAVE. Recortar una fecha a su
175
+ * grano es de quien conoce el dato, no del sistema. */
176
+ of: PileOf<T>;
177
+ /** Cómo se lee una clave. Sin esto, una fecha la nombra el calendario del
178
+ * sistema en el idioma activo y lo demás se dibuja tal cual. */
179
+ label?: PileLabelOf;
180
+ /**
181
+ * El árbol YA armado, cuando lo contó quien tiene el conjunto entero.
182
+ *
183
+ * Existe porque un conteo que sólo conoce la página no es un conteo: «187
184
+ * sintéticos» no lo pueden contestar las doce filas que se trajeron. Quién
185
+ * cuenta no es asunto de esta capa — dibuja el mismo árbol en los dos casos.
186
+ *
187
+ * Un árbol contado afuera llega con sus rótulos PUESTOS, y esta capa no se los
188
+ * toca: quien lo tradujo sabe cuál de sus claves es una fecha y cuál es un
189
+ * código con nombre propio. `dateLabel` está exportado para que los ponga con
190
+ * las mismas palabras que el árbol armado acá.
191
+ */
192
+ piles?: readonly Pile<T>[];
193
+ /** Qué montones están plegados, por `pathKey(pile.path)`. */
194
+ collapsed?: readonly string[];
195
+ onToggle?: (key: string) => void;
196
+ };
197
+ /**
198
+ * El árbol que hay que dibujar, o `null` si no se agrupa.
199
+ *
200
+ * Es la única línea que un componente necesita escribir para volverse agrupable:
201
+ * decide entre el árbol que le pasaron y el que arma con las cosas en la mano, y
202
+ * contesta `null` cuando no hay nada que partir — que es distinto de un árbol
203
+ * vacío, porque un árbol vacío significa «se agrupó y no quedó nada».
204
+ */
205
+ export declare function pilesOf<T>(items: readonly T[], grouping: Grouping<T> | undefined): readonly Pile<T>[] | null;
206
+ /** Si un montón está abierto, según lo plegado. Abierto es el default: agrupar y
207
+ * después tener que abrir cada montón son dos gestos para lo que se pidió en
208
+ * uno. */
209
+ export declare function pileIsOpen<T>(pile: Pile<T>, grouping: Grouping<T> | undefined): boolean;
210
+ /** La clave de plegado de una ruta. El separador es un carácter que no aparece
211
+ * en un valor real, así que dos rutas distintas no pueden producir la misma
212
+ * clave por concatenación — `["a", "b"]` y `["ab"]` sí podrían con un
213
+ * separador escribible. */
214
+ export declare function pathKey(path: readonly string[]): string;
215
+ /** Qué montón le toca a cada fila en cada nivel: su CLAVE. Recortar una fecha a
216
+ * su grano es cosa de quien conoce el dato —`dateKey` la recorta con el mismo
217
+ * texto que el motor— y ponerle nombre es cosa del rótulo. */
218
+ export type PileOf<T> = (item: T, level: GroupLevel) => string;
219
+ /**
220
+ * Cómo se lee la clave de un montón.
221
+ *
222
+ * `within` son los granos que los montones de ARRIBA, del mismo campo, ya
223
+ * dijeron: con el año afuera, un mes se rotula «Septiembre» y no «Septiembre de
224
+ * 2026». Decirlo dos veces llena la sangría con lo que está dos renglones más
225
+ * arriba.
226
+ */
227
+ export type PileLabelOf = (key: string, level: GroupLevel, within: readonly GroupGrain[]) => string;
228
+ /** El rótulo por default: una fecha la nombra el calendario en el idioma activo,
229
+ * y lo que no es una fecha se dibuja tal cual —«sintético» se identifica y se
230
+ * lee con la misma palabra, y traducirlo sería inventar un valor que nadie
231
+ * guardó. */
232
+ export declare function pileLabel(key: string, level: GroupLevel, within: readonly GroupGrain[]): string;
233
+ /**
234
+ * CÓMO SE LEE UNA RUTA de claves, tramo por tramo.
235
+ *
236
+ * La clave identifica y el rótulo se lee: «2026-09» es lo que el motor escribe y
237
+ * «Septiembre» lo que se dibuja. Cualquiera que tenga una ruta —el eje de un
238
+ * pivote, el título de un montón, una miga— la dice con esto, porque una ruta
239
+ * que se lee distinta según quién la dibuje es el mismo corte con dos caras.
240
+ *
241
+ * `within` sale de los niveles de ARRIBA del mismo campo: con el año afuera, el
242
+ * mes se dice «Septiembre» y no «Septiembre de 2026», porque eso ya está escrito
243
+ * un tramo antes.
244
+ */
245
+ export declare function pathLabels(levels: readonly GroupLevel[], path: readonly string[], label?: PileLabelOf): string[];
246
+ /**
247
+ * Arma el árbol de montones a partir de las filas que hay EN LA MANO.
248
+ *
249
+ * Sirve cuando el conjunto entero está en el navegador. Cuando no lo está —un
250
+ * catálogo de ciento ochenta y siete del que se bajaron doce—, los montones los
251
+ * cuenta quien los guarda y esto no se usa: la presentación recibe `piles` ya
252
+ * hechos. Las dos formas dibujan igual porque dibujan el mismo tipo.
253
+ *
254
+ * El orden de los montones es el de PRIMERA APARICIÓN de cada valor, en cada
255
+ * nivel. No se ordena alfabéticamente: el orden de las filas ya lo decidió
256
+ * alguien —una columna, un criterio, el motor— y reordenar los montones acá lo
257
+ * contradiría.
258
+ */
259
+ export declare function pilesFrom<T>(items: readonly T[], levels: readonly GroupLevel[], of: PileOf<T>, label?: PileLabelOf): readonly Pile<T>[];
260
+ /**
261
+ * La ruta de UNA fila: el montón que le toca en cada nivel.
262
+ *
263
+ * Es la identidad del montón más profundo que la contiene, sin armar el árbol.
264
+ * Sirve para preguntar «¿estas dos filas son vecinas?», que con un solo nivel se
265
+ * contestaba comparando una clave y con N hay que comparar la ruta entera: dos
266
+ * datasets del mismo mes son vecinos sólo si además comparten la procedencia,
267
+ * porque si no están en montones distintos aunque el último tramo coincida.
268
+ */
269
+ export declare function itemPath<T>(item: T, levels: readonly GroupLevel[], of: PileOf<T>): string[];
270
+ /** Las filas de un árbol, en el orden en que se dibujan. Lo usan las
271
+ * presentaciones que necesitan la secuencia y no el árbol —la planilla
272
+ * virtualizada, que cuenta índices— y el que quiera saber qué quedó visible. */
273
+ export declare function pileItems<T>(piles: readonly Pile<T>[]): readonly T[];
274
+ /** Cuántas filas hay en total. Suma los conteos del primer nivel, que ya
275
+ * incluyen los de abajo — no recorre las filas, porque puede no tenerlas. */
276
+ export declare function pileCount<T>(piles: readonly Pile<T>[]): number;
277
+ /** Mueve un nivel `delta` lugares. Se queda en los bordes en vez de dar la
278
+ * vuelta: llegar al primero y volver al último no es lo que nadie espera de una
279
+ * flecha «subir». El orden de los niveles ES la jerarquía, así que esto cambia
280
+ * la pregunta y no sólo la lista. */
281
+ export declare function moveLevel(levels: readonly GroupLevel[], field: string, delta: number): GroupLevel[];
Binary file
@@ -0,0 +1,14 @@
1
+ export { currentCopy, currentCopyLocale, ENGLISH_COPY, fillCopy, installCopy, mergeCopy, type UiCopy, type UiCopyOverride, UiCopyProvider, useUiCopy, } from "./copy.js";
2
+ export { byDensity, type Density, DensityProvider, useDensity, } from "./density.js";
3
+ export { bySurface, SurfaceProvider, useSurface } from "./surface.js";
4
+ export { applyTheme, isTheme, type ResolvedTheme, resolveTheme, type Theme, THEME_ATTRIBUTE, ThemeProvider, type ThemeProviderProps, THEMES, useTheme, } from "./theme.js";
5
+ export type { Size, Surface, Tone } from "./types.js";
6
+ /** El castellano del sistema, para quien lo quiera instalar entero. */
7
+ export { SPANISH_COPY } from "./copy.es.js";
8
+ export { flatten, loose, pick, pickAll, propsOf, slot, slotOf, type Slotted, } from "./slots.js";
9
+ export { dateKey, dateLabel, grainName, monthName, } from "./calendar.js";
10
+ export { GRAIN_ORDER, type GroupableField, type GroupGrain, type Grouping, type GroupLevel, itemPath, levelKey, moveLevel, normalizeLevels, pathKey, pathLabels, type Pile, pileCount, pileIsOpen, pileItems, pileLabel, type PileLabelOf, type PileOf, pilesFrom, pilesOf, } from "./grouping.js";
11
+ export { axisLabels, axisSpans, keyStarts, type Pivot, type PivotAxis, type PivotCell, type PivotCrossing, type PivotFold, pivotFrom, pivotIsEmpty, type PivotKey, type PivotLevel, type PivotMargin, type PivotMeasure, pivotOf, type PivotSource, type PivotSpec, } from "./pivot.js";
12
+ export { downloadPivot, pivotSheet, type PivotSheetOptions, pivotXlsx, } from "./pivotSheet.js";
13
+ export { STICKY_TOP, stickyReset, stickyTop, useScrollBox, useStickyLayer, } from "./sticky.js";
14
+ export { columnName, downloadXlsx, writeXlsx, type XlsxCell, type XlsxMerge, type XlsxSheet, } from "./xlsx.js";
@@ -0,0 +1,30 @@
1
+ /* What is shared by more than one family and belongs to none of them. */
2
+ export { currentCopy, currentCopyLocale, ENGLISH_COPY, fillCopy, installCopy, mergeCopy, UiCopyProvider, useUiCopy, } from "./copy.js";
3
+ export { byDensity, DensityProvider, useDensity, } from "./density.js";
4
+ /* EL TEMA — claro, oscuro o el del sistema operativo. Las paletas viven en `tokens.css`; esto
5
+ sólo escribe `data-theme`. */
6
+ export { bySurface, SurfaceProvider, useSurface } from "./surface.js";
7
+ export { applyTheme, isTheme, resolveTheme, THEME_ATTRIBUTE, ThemeProvider, THEMES, useTheme, } from "./theme.js";
8
+ /** El castellano del sistema, para quien lo quiera instalar entero. */
9
+ export { SPANISH_COPY } from "./copy.es.js";
10
+ /* LAS RANURAS — cómo un arquetipo se escribe como ÁRBOL. Vive acá y no adentro
11
+ de uno porque lo hablan todos los que lo son: mientras estuvo escondido en
12
+ `Record.tsx`, ser un árbol era un privilegio de los registros. */
13
+ export { flatten, loose, pick, pickAll, propsOf, slot, slotOf, } from "./slots.js";
14
+ /* EL CALENDARIO — de una fecha a una clave y de una clave a un rótulo. Los meses
15
+ y los días de la semana los dice `Intl` con el `locale` de la copia; la semana
16
+ y el trimestre son las dos únicas palabras que hay que escribir. */
17
+ export { dateKey, dateLabel, grainName, monthName, } from "./calendar.js";
18
+ /* LA AGRUPACIÓN — el vocabulario, que hablan las dos capas: la lista arma el
19
+ árbol de montones y la tabla lo dibuja. Vive acá y no en `contexts/list`
20
+ porque una primitiva no puede importar de un contexto. */
21
+ export { GRAIN_ORDER, itemPath, levelKey, moveLevel, normalizeLevels, pathKey, pathLabels, pileCount, pileIsOpen, pileItems, pileLabel, pilesFrom, pilesOf, } from "./grouping.js";
22
+ /* EL PIVOTE — el mismo reparto: el vocabulario acá, la grilla en `primitives`.
23
+ Que los márgenes vengan de la base y que un agujero no sea un cero son reglas
24
+ del CONTRATO, no del dibujo, y por eso viven de este lado. */
25
+ export { axisLabels, axisSpans, keyStarts, pivotFrom, pivotIsEmpty, pivotOf, } from "./pivot.js";
26
+ /* LA PLANILLA: la misma grilla, en un archivo. El escritor es genérico y no
27
+ sabe de pivotes; `pivotSheet` es el que traduce uno. */
28
+ export { downloadPivot, pivotSheet, pivotXlsx, } from "./pivotSheet.js";
29
+ export { STICKY_TOP, stickyReset, stickyTop, useScrollBox, useStickyLayer, } from "./sticky.js";
30
+ export { columnName, downloadXlsx, writeXlsx, } from "./xlsx.js";
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Context: `--container-handheld` (40rem, `tokens.css`) in pixels. A container query cannot
3
+ * swap a `<table>` for a list, so the two components that must decide in code — `ListView`
4
+ * (which presentations to offer) and `EditableTable` (grid or stacked cards) — ask a
5
+ * `ResizeObserver` for pixels and compare against this one figure. It used to be written
6
+ * twice, `HANDHELD` in one and `NARROW_LIST` in the other, and the day one moved the two
7
+ * would have disagreed about what a phone is. Keep it equal to the token.
8
+ */
9
+ export declare const HANDHELD_WIDTH = 640;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Context: `--container-handheld` (40rem, `tokens.css`) in pixels. A container query cannot
3
+ * swap a `<table>` for a list, so the two components that must decide in code — `ListView`
4
+ * (which presentations to offer) and `EditableTable` (grid or stacked cards) — ask a
5
+ * `ResizeObserver` for pixels and compare against this one figure. It used to be written
6
+ * twice, `HANDHELD` in one and `NARROW_LIST` in the other, and the day one moved the two
7
+ * would have disagreed about what a phone is. Keep it equal to the token.
8
+ */
9
+ export const HANDHELD_WIDTH = 640;
@@ -0,0 +1,222 @@
1
+ import { type GroupLevel, type PileLabelOf, type PileOf } from "./grouping.js";
2
+ /**
3
+ * EL PIVOTE: montones cruzados por montones.
4
+ *
5
+ * Agrupar parte un conjunto por lo que sus filas comparten. Pivotear lo parte
6
+ * DOS VECES a la vez, por ejes distintos, y lee el número donde los dos cortes
7
+ * se encuentran: el cliente hacia abajo, el mes hacia la derecha, y en el
8
+ * cruce cuántas filas hay y cuánto suman.
9
+ *
10
+ * ── Tres reglas, y ninguna es cosmética ─────────────────────────────
11
+ *
12
+ * 1. **La grilla se dibuja desde los EJES, no desde los cruces.** `rows.keys` y
13
+ * `columns.keys` traen cada clave que apareció, en orden; los cruces se
14
+ * PREGUNTAN de a uno. Un pivote es mayormente agujeros —doce clientes
15
+ * por veinticuatro meses son 288 celdas y cuarenta con filas— y deducir la
16
+ * grilla recorriendo los cruces deja afuera el mes en que no pasó nada, que
17
+ * es justo la columna que alguien está buscando.
18
+ *
19
+ * 2. **Los márgenes vienen plegados de la BASE.** Un promedio de promedios no
20
+ * es un promedio y una mediana de medianas no es nada, así que `rowTotal`,
21
+ * `columnTotal` y `total` se reciben: esta capa nunca los inventa sumando la
22
+ * fila que acaba de dibujar. Sin ellos no hay banda de totales, que es la
23
+ * respuesta honesta cuando nadie los calculó.
24
+ *
25
+ * 3. **Un agujero no es un cero.** `undefined` es «ahí no hay ninguna fila» y
26
+ * `0` es «hay filas y suman cero». La grilla los dibuja distinto porque
27
+ * significan cosas distintas.
28
+ *
29
+ * ── Qué se PIDE y qué se DIBUJA ─────────────────────────────────────
30
+ *
31
+ * Igual que con los montones: `PivotSpec` es lo que alguien pidió —por qué
32
+ * campos partir cada eje, qué medidas plegar— y `Pivot` es lo que se dibuja, ya
33
+ * plegado. Están separados porque plegar no siempre lo hace esta máquina: un
34
+ * libro de ventas de ciento ochenta y siete del que se bajaron doce lo pliega quien lo
35
+ * guarda, y `pivotFrom` es un helper para cuando el conjunto entero está en el
36
+ * navegador, no el único camino.
37
+ *
38
+ * **Esto no conoce ningún motor.** Ni criteria, ni cursores, ni transporte: un
39
+ * eje acá es una lista de rutas legibles y un cruce es un conteo con números al
40
+ * lado. Quien traduzca la respuesta de un servidor a esta forma vive afuera, y
41
+ * por eso la misma grilla sirve para un pivote armado en el navegador y para uno
42
+ * plegado a mil kilómetros.
43
+ */
44
+ /**
45
+ * La clave de una fila o de una columna: la RUTA por los niveles de su eje, ya
46
+ * legible.
47
+ *
48
+ * Es una ruta y no un valor por la misma razón que la de un montón: con dos
49
+ * niveles puestos, «2026-09» puede ser un mes adentro de «Ferretería Sur» y otro
50
+ * adentro de «Distribuidora Andina», y son dos filas distintas de la grilla.
51
+ */
52
+ export type PivotKey = readonly string[];
53
+ /**
54
+ * UN NIVEL de un eje: por qué se partió, y cómo se lee.
55
+ *
56
+ * Lleva el nivel ENTERO y no sólo su rótulo porque el rótulo de un nivel no
57
+ * alcanza para leer sus claves: con «registrado» a la vista, «2026-09» sigue
58
+ * siendo «2026-09». El grano es lo que deja decir «Septiembre», y el campo es lo
59
+ * que deja saber que el mes cuelga del año de más arriba y entonces no hace
60
+ * falta repetirlo.
61
+ */
62
+ export type PivotLevel = GroupLevel & {
63
+ /** Cómo se llama este corte: es lo que dice la esquina de la grilla. Sin él,
64
+ * una columna no aclara si es cuándo se registró o cuándo se corrió. */
65
+ label: string;
66
+ };
67
+ /** Un EJE del pivote: qué se preguntó, y qué claves aparecieron. */
68
+ export type PivotAxis = {
69
+ /** Los niveles, de afuera hacia adentro. */
70
+ levels: readonly PivotLevel[];
71
+ /** Cada clave que apareció, en orden. **La grilla se dibuja desde acá.** */
72
+ keys: readonly PivotKey[];
73
+ };
74
+ /**
75
+ * CÓMO SE LEE UNA CLAVE del eje, tramo por tramo.
76
+ *
77
+ * La clave identifica —«2026-09» es lo que el motor escribe y lo que se compara
78
+ * con lo que contó el servidor— y el rótulo se lee. Son dos textos, igual que en
79
+ * un montón, y por la misma razón: con el rótulo por identidad, dos septiembres
80
+ * de años distintos serían el mismo.
81
+ *
82
+ * `within` sale de los niveles de ARRIBA del mismo campo: con el año afuera, el
83
+ * mes se dice «Septiembre» y no «Septiembre de 2026», porque eso ya está escrito
84
+ * dos columnas antes.
85
+ */
86
+ export declare function axisLabels(axis: PivotAxis, key: PivotKey, label?: PileLabelOf): readonly string[];
87
+ /** Una MEDIDA: uno de los números que se pliegan en cada cruce. */
88
+ export type PivotMeasure = {
89
+ id: string;
90
+ header: string;
91
+ /** Para un porcentaje o una variación, que no se leen como un importe. */
92
+ format?: (value: number) => string;
93
+ /**
94
+ * Cómo se lee la medida en una PLANILLA: el código de formato de Excel,
95
+ * `#,##0.00`, `0.0%`, `#,##0 "Bs."`.
96
+ *
97
+ * Va aparte de `format` porque son dos cosas distintas: `format` es una
98
+ * función de JavaScript, y un archivo no se puede llevar una función adentro.
99
+ * Sin esto el número sale con el formato general — sigue siendo un número y se
100
+ * sigue pudiendo sumar, que es lo que no se puede perder.
101
+ */
102
+ numberFormat?: string;
103
+ };
104
+ /**
105
+ * Un CRUCE ya plegado: cuántas filas hay debajo y qué dan las medidas.
106
+ *
107
+ * `count` va aparte de las medidas y no como una más: es la única que siempre se
108
+ * puede contestar, y es la que dice si una celda vacía está vacía porque no hay
109
+ * filas o porque las que hay no tienen ese número.
110
+ */
111
+ export type PivotCell = {
112
+ count: number;
113
+ /** Un número por medida, por id. `null` es «esta medida no se contesta acá» y
114
+ * es distinto de `0`. */
115
+ values: Readonly<Record<string, number | null>>;
116
+ };
117
+ /** EL PIVOTE, listo para dibujar. */
118
+ export type Pivot = {
119
+ rows: PivotAxis;
120
+ columns: PivotAxis;
121
+ measures: readonly PivotMeasure[];
122
+ /** El cruce donde una fila encuentra a una columna, o `undefined` cuando no
123
+ * hay ninguna fila ahí. Se pregunta y no se recorre: ver la regla 1. */
124
+ cell: (row: PivotKey, column: PivotKey) => PivotCell | undefined;
125
+ /** La fila entera, plegada de la base. Ausente = no hay banda de totales a la
126
+ * derecha, porque nadie los calculó y acá no se suman celdas. */
127
+ rowTotal?: (row: PivotKey) => PivotCell | undefined;
128
+ /** La columna entera, plegada de la base. */
129
+ columnTotal?: (column: PivotKey) => PivotCell | undefined;
130
+ /** Todo lo que entró, plegado una vez. */
131
+ total?: PivotCell;
132
+ };
133
+ /** Un cruce, con sus dos claves. Es la forma en que viaja una grilla dispersa:
134
+ * sólo los cruces que tienen filas. */
135
+ export type PivotCrossing = PivotCell & {
136
+ row: PivotKey;
137
+ column: PivotKey;
138
+ };
139
+ /** Un margen: la clave de su eje y lo que da esa fila —o esa columna— entera. */
140
+ export type PivotMargin = PivotCell & {
141
+ key: PivotKey;
142
+ };
143
+ export type PivotSource = {
144
+ rows: PivotAxis;
145
+ columns: PivotAxis;
146
+ measures: readonly PivotMeasure[];
147
+ /** Sólo los cruces con filas. Los que faltan son agujeros. */
148
+ crossings: readonly PivotCrossing[];
149
+ /** Uno por clave de fila. Sin esto no hay columna de totales. */
150
+ rowMargins?: readonly PivotMargin[];
151
+ /** Uno por clave de columna. Sin esto no hay fila de totales. */
152
+ columnMargins?: readonly PivotMargin[];
153
+ total?: PivotCell;
154
+ };
155
+ /**
156
+ * Indexa un pivote que ya viene plegado.
157
+ *
158
+ * Los cruces viajan como lista —es lo que sabe serializar cualquier transporte—
159
+ * y se dibujan preguntando de a uno, así que en el medio hace falta un índice.
160
+ * Se arma una vez acá y no en cada celda de cada render: una grilla de 288
161
+ * celdas buscando en una lista de 40 son 11.520 comparaciones por pintada.
162
+ */
163
+ export declare function pivotOf(source: PivotSource): Pivot;
164
+ /** Una medida y cómo se pliega. El pliegue recibe las filas de la BASE —las del
165
+ * cruce, las de la fila entera, las de todo—, que es lo que hace que el margen
166
+ * salga del mismo lugar que la celda y no de sumar celdas. */
167
+ export type PivotFold<T> = PivotMeasure & {
168
+ fold: (items: readonly T[]) => number | null;
169
+ };
170
+ export type PivotSpec<T> = {
171
+ /** Los niveles del eje vertical, de afuera hacia adentro. */
172
+ rows: readonly GroupLevel[];
173
+ /** Los niveles del eje horizontal. */
174
+ columns: readonly GroupLevel[];
175
+ /** A qué montón va cada fila, en cada nivel de cada eje, ya legible. Es el
176
+ * mismo contrato que agrupa una lista: recortar una fecha a su grano es de
177
+ * quien conoce el dato. */
178
+ of: PileOf<T>;
179
+ measures: readonly PivotFold<T>[];
180
+ /** Cómo se llama cada nivel. Sin esto se muestra el nombre del campo. */
181
+ labelOf?: (level: GroupLevel) => string;
182
+ };
183
+ /**
184
+ * Arma el pivote con las filas que hay EN LA MANO.
185
+ *
186
+ * Sirve cuando el conjunto entero está en el navegador. Cuando no lo está, el
187
+ * pivote lo pliega quien guarda los datos y esto no se usa: la grilla recibe un
188
+ * `Pivot` de `pivotOf` y dibuja igual, porque dibuja el mismo tipo.
189
+ *
190
+ * **Los márgenes se pliegan sobre las filas de la base y no sobre los cruces**,
191
+ * que es la regla 2 escrita en código: el margen de «Ferretería Sur» pliega sus 187
192
+ * facturas de una, no los doce números mensuales que ya se dibujaron. Es
193
+ * lo único que hace que una medida que no sea una suma —un promedio, una
194
+ * mediana, un distintos— diga la verdad en el borde.
195
+ */
196
+ export declare function pivotFrom<T>(items: readonly T[], spec: PivotSpec<T>): Pivot;
197
+ /** Si el pivote no tiene ni una fila que cruzar. Un eje vacío no es un pivote
198
+ * chico: es la vista vacía, y se dice con la frase del conjunto y no con una
199
+ * grilla de un renglón. */
200
+ export declare function pivotIsEmpty(pivot: Pivot): boolean;
201
+ /**
202
+ * Los tramos de una clave que hay que ESCRIBIR, comparada con la anterior.
203
+ *
204
+ * En el área de filas de un pivote, el valor de un nivel se escribe sólo cuando
205
+ * cambia: repetir «Ferretería Sur» en las doce filas de sus doce meses convierte la
206
+ * jerarquía en una columna de ruido y hace desaparecer justamente el corte que
207
+ * se pidió. Devuelve, por nivel, si ese tramo arranca acá.
208
+ */
209
+ export declare function keyStarts(key: PivotKey, previous: PivotKey | undefined): readonly boolean[];
210
+ /**
211
+ * Cuánto abarca cada tramo del eje horizontal, nivel por nivel.
212
+ *
213
+ * El encabezado de un pivote es una jerarquía acostada: un renglón por nivel, y
214
+ * cada rótulo cubriendo las columnas que cuelgan de él. Esto lo resuelve una vez
215
+ * —de a tramos consecutivos iguales, que es lo que hace que «2026» cubra sus
216
+ * cuatro trimestres— y la grilla sólo lo dibuja.
217
+ */
218
+ export declare function axisSpans(axis: PivotAxis, level: number): readonly {
219
+ label: string;
220
+ span: number;
221
+ at: number;
222
+ }[];