@sincpro/web-ui 0.0.0-stage → 0.2.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 (376) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -2
  3. package/dist/components/activity/Activity.d.ts +69 -0
  4. package/dist/components/activity/Activity.js +279 -0
  5. package/dist/components/activity/Messages.d.ts +66 -0
  6. package/dist/components/activity/Messages.js +46 -0
  7. package/dist/components/activity/Timeline.d.ts +21 -0
  8. package/dist/components/activity/Timeline.js +30 -0
  9. package/dist/components/activity/index.d.ts +3 -0
  10. package/dist/components/activity/index.js +4 -0
  11. package/dist/components/assist/AssistMark.d.ts +64 -0
  12. package/dist/components/assist/AssistMark.js +108 -0
  13. package/dist/components/assist/AssistPending.d.ts +24 -0
  14. package/dist/components/assist/AssistPending.js +26 -0
  15. package/dist/components/assist/AssistSuggestion.d.ts +42 -0
  16. package/dist/components/assist/AssistSuggestion.js +55 -0
  17. package/dist/components/assist/ChangeReview.d.ts +56 -0
  18. package/dist/components/assist/ChangeReview.js +121 -0
  19. package/dist/components/assist/assist.d.ts +77 -0
  20. package/dist/components/assist/assist.js +87 -0
  21. package/dist/components/assist/index.d.ts +5 -0
  22. package/dist/components/assist/index.js +7 -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 +47 -0
  26. package/dist/components/form/Sheet.js +90 -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 +111 -0
  40. package/dist/components/lines/LineItems.js +317 -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 +112 -0
  52. package/dist/components/listing/ListingBar.js +144 -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 +110 -0
  60. package/dist/components/listing/Row.js +123 -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 +75 -0
  96. package/dist/components/record/RecordHeader.js +104 -0
  97. package/dist/components/record/RecordNotices.d.ts +37 -0
  98. package/dist/components/record/RecordNotices.js +75 -0
  99. package/dist/components/record/RecordSkeleton.d.ts +3 -0
  100. package/dist/components/record/RecordSkeleton.js +21 -0
  101. package/dist/components/record/SmartButtons.d.ts +35 -0
  102. package/dist/components/record/SmartButtons.js +38 -0
  103. package/dist/components/record/StatusBar.d.ts +51 -0
  104. package/dist/components/record/StatusBar.js +168 -0
  105. package/dist/components/record/ThumbBar.d.ts +36 -0
  106. package/dist/components/record/ThumbBar.js +86 -0
  107. package/dist/components/record/index.d.ts +6 -0
  108. package/dist/components/record/index.js +8 -0
  109. package/dist/components/search/CriteriaBuilder.d.ts +58 -0
  110. package/dist/components/search/CriteriaBuilder.js +278 -0
  111. package/dist/components/search/CriteriaChips.d.ts +22 -0
  112. package/dist/components/search/CriteriaChips.js +64 -0
  113. package/dist/components/search/FilterBuilder.d.ts +142 -0
  114. package/dist/components/search/FilterBuilder.js +421 -0
  115. package/dist/components/search/JoinWord.d.ts +8 -0
  116. package/dist/components/search/JoinWord.js +47 -0
  117. package/dist/components/search/JsonEditor.d.ts +19 -0
  118. package/dist/components/search/JsonEditor.js +78 -0
  119. package/dist/components/search/SearchBar.d.ts +78 -0
  120. package/dist/components/search/SearchBar.js +387 -0
  121. package/dist/components/search/criteria.d.ts +116 -0
  122. package/dist/components/search/criteria.js +159 -0
  123. package/dist/components/search/datePeriods.d.ts +122 -0
  124. package/dist/components/search/datePeriods.js +134 -0
  125. package/dist/components/search/dateRanges.d.ts +54 -0
  126. package/dist/components/search/dateRanges.js +89 -0
  127. package/dist/components/search/index.d.ts +9 -0
  128. package/dist/components/search/index.js +20 -0
  129. package/dist/components/search/model.d.ts +54 -0
  130. package/dist/components/search/model.js +37 -0
  131. package/dist/components/search/query.d.ts +166 -0
  132. package/dist/components/search/query.js +436 -0
  133. package/dist/components/shell/AppFrame.d.ts +14 -0
  134. package/dist/components/shell/AppFrame.js +80 -0
  135. package/dist/components/shell/TopBar.d.ts +73 -0
  136. package/dist/components/shell/TopBar.js +54 -0
  137. package/dist/components/shell/headerSlot.d.ts +17 -0
  138. package/dist/components/shell/headerSlot.js +21 -0
  139. package/dist/components/shell/index.d.ts +2 -0
  140. package/dist/components/shell/index.js +3 -0
  141. package/dist/foundations/aria.d.ts +14 -0
  142. package/dist/foundations/aria.js +18 -0
  143. package/dist/foundations/calendar.d.ts +28 -0
  144. package/dist/foundations/calendar.js +183 -0
  145. package/dist/foundations/copy.d.ts +703 -0
  146. package/dist/foundations/copy.es.d.ts +2 -0
  147. package/dist/foundations/copy.es.js +430 -0
  148. package/dist/foundations/copy.js +520 -0
  149. package/dist/foundations/density.d.ts +16 -0
  150. package/dist/foundations/density.js +21 -0
  151. package/dist/foundations/grouping.d.ts +281 -0
  152. package/dist/foundations/grouping.js +0 -0
  153. package/dist/foundations/index.d.ts +14 -0
  154. package/dist/foundations/index.js +30 -0
  155. package/dist/foundations/layout.d.ts +9 -0
  156. package/dist/foundations/layout.js +9 -0
  157. package/dist/foundations/pivot.d.ts +222 -0
  158. package/dist/foundations/pivot.js +198 -0
  159. package/dist/foundations/pivotSheet.d.ts +61 -0
  160. package/dist/foundations/pivotSheet.js +0 -0
  161. package/dist/foundations/slots.d.ts +67 -0
  162. package/dist/foundations/slots.js +63 -0
  163. package/dist/foundations/sticky.d.ts +53 -0
  164. package/dist/foundations/sticky.js +150 -0
  165. package/dist/foundations/surface.d.ts +9 -0
  166. package/dist/foundations/surface.js +26 -0
  167. package/dist/foundations/theme.d.ts +42 -0
  168. package/dist/foundations/theme.js +88 -0
  169. package/dist/foundations/types.d.ts +23 -0
  170. package/dist/foundations/types.js +50 -0
  171. package/dist/foundations/variants.d.ts +19 -0
  172. package/dist/foundations/variants.js +48 -0
  173. package/dist/foundations/xlsx.d.ts +86 -0
  174. package/dist/foundations/xlsx.js +0 -0
  175. package/dist/index.d.ts +19 -0
  176. package/dist/index.js +19 -0
  177. package/dist/primitives/block/Block.d.ts +66 -0
  178. package/dist/primitives/block/Block.js +34 -0
  179. package/dist/primitives/block/Line.d.ts +18 -0
  180. package/dist/primitives/block/Line.js +45 -0
  181. package/dist/primitives/block/SectionGrid.d.ts +30 -0
  182. package/dist/primitives/block/SectionGrid.js +29 -0
  183. package/dist/primitives/block/Steps.d.ts +76 -0
  184. package/dist/primitives/block/Steps.js +43 -0
  185. package/dist/primitives/block/index.d.ts +4 -0
  186. package/dist/primitives/block/index.js +7 -0
  187. package/dist/primitives/button/Button.d.ts +137 -0
  188. package/dist/primitives/button/Button.js +234 -0
  189. package/dist/primitives/button/index.d.ts +1 -0
  190. package/dist/primitives/button/index.js +2 -0
  191. package/dist/primitives/cell/CellStack.d.ts +47 -0
  192. package/dist/primitives/cell/CellStack.js +33 -0
  193. package/dist/primitives/cell/index.d.ts +1 -0
  194. package/dist/primitives/cell/index.js +3 -0
  195. package/dist/primitives/choice/ComboBox.d.ts +19 -0
  196. package/dist/primitives/choice/ComboBox.js +52 -0
  197. package/dist/primitives/choice/RadioGroup.d.ts +18 -0
  198. package/dist/primitives/choice/RadioGroup.js +50 -0
  199. package/dist/primitives/choice/SearchField.d.ts +33 -0
  200. package/dist/primitives/choice/SearchField.js +46 -0
  201. package/dist/primitives/choice/SegmentedControl.d.ts +16 -0
  202. package/dist/primitives/choice/SegmentedControl.js +69 -0
  203. package/dist/primitives/choice/Slider.d.ts +16 -0
  204. package/dist/primitives/choice/Slider.js +46 -0
  205. package/dist/primitives/choice/Switch.d.ts +14 -0
  206. package/dist/primitives/choice/Switch.js +65 -0
  207. package/dist/primitives/choice/ThemeSwitcher.d.ts +10 -0
  208. package/dist/primitives/choice/ThemeSwitcher.js +25 -0
  209. package/dist/primitives/choice/index.d.ts +8 -0
  210. package/dist/primitives/choice/index.js +11 -0
  211. package/dist/primitives/choice/options.d.ts +28 -0
  212. package/dist/primitives/choice/options.js +6 -0
  213. package/dist/primitives/date/Calendar.d.ts +31 -0
  214. package/dist/primitives/date/Calendar.js +134 -0
  215. package/dist/primitives/date/DatePicker.d.ts +42 -0
  216. package/dist/primitives/date/DatePicker.js +103 -0
  217. package/dist/primitives/date/DateTime.d.ts +35 -0
  218. package/dist/primitives/date/DateTime.js +100 -0
  219. package/dist/primitives/date/index.d.ts +3 -0
  220. package/dist/primitives/date/index.js +6 -0
  221. package/dist/primitives/dialog/Dialog.d.ts +118 -0
  222. package/dist/primitives/dialog/Dialog.js +121 -0
  223. package/dist/primitives/dialog/Drill.d.ts +90 -0
  224. package/dist/primitives/dialog/Drill.js +172 -0
  225. package/dist/primitives/dialog/index.d.ts +2 -0
  226. package/dist/primitives/dialog/index.js +4 -0
  227. package/dist/primitives/disclosure/Disclosure.d.ts +36 -0
  228. package/dist/primitives/disclosure/Disclosure.js +52 -0
  229. package/dist/primitives/disclosure/index.d.ts +1 -0
  230. package/dist/primitives/disclosure/index.js +2 -0
  231. package/dist/primitives/field/Checks.d.ts +57 -0
  232. package/dist/primitives/field/Checks.js +72 -0
  233. package/dist/primitives/field/DropZone.d.ts +42 -0
  234. package/dist/primitives/field/DropZone.js +52 -0
  235. package/dist/primitives/field/Field.d.ts +178 -0
  236. package/dist/primitives/field/Field.js +251 -0
  237. package/dist/primitives/field/Suggest.d.ts +48 -0
  238. package/dist/primitives/field/Suggest.js +43 -0
  239. package/dist/primitives/field/aria.d.ts +61 -0
  240. package/dist/primitives/field/aria.js +70 -0
  241. package/dist/primitives/field/context.d.ts +30 -0
  242. package/dist/primitives/field/context.js +13 -0
  243. package/dist/primitives/field/copy.d.ts +16 -0
  244. package/dist/primitives/field/copy.js +69 -0
  245. package/dist/primitives/field/index.d.ts +9 -0
  246. package/dist/primitives/field/index.js +15 -0
  247. package/dist/primitives/field/layout.d.ts +24 -0
  248. package/dist/primitives/field/layout.js +10 -0
  249. package/dist/primitives/field/mode.d.ts +9 -0
  250. package/dist/primitives/field/mode.js +13 -0
  251. package/dist/primitives/field/note.d.ts +55 -0
  252. package/dist/primitives/field/note.js +117 -0
  253. package/dist/primitives/hint/Hint.d.ts +31 -0
  254. package/dist/primitives/hint/Hint.js +42 -0
  255. package/dist/primitives/hint/index.d.ts +1 -0
  256. package/dist/primitives/hint/index.js +1 -0
  257. package/dist/primitives/index.d.ts +20 -0
  258. package/dist/primitives/index.js +21 -0
  259. package/dist/primitives/menu/Menu.d.ts +128 -0
  260. package/dist/primitives/menu/Menu.js +89 -0
  261. package/dist/primitives/menu/index.d.ts +1 -0
  262. package/dist/primitives/menu/index.js +2 -0
  263. package/dist/primitives/notice/Callout.d.ts +49 -0
  264. package/dist/primitives/notice/Callout.js +28 -0
  265. package/dist/primitives/notice/Flag.d.ts +13 -0
  266. package/dist/primitives/notice/Flag.js +31 -0
  267. package/dist/primitives/notice/Notice.d.ts +45 -0
  268. package/dist/primitives/notice/Notice.js +61 -0
  269. package/dist/primitives/notice/Toast.d.ts +55 -0
  270. package/dist/primitives/notice/Toast.js +142 -0
  271. package/dist/primitives/notice/index.d.ts +4 -0
  272. package/dist/primitives/notice/index.js +6 -0
  273. package/dist/primitives/overlay/Popover.d.ts +6 -0
  274. package/dist/primitives/overlay/Popover.js +27 -0
  275. package/dist/primitives/overlay/PopoverTrigger.d.ts +55 -0
  276. package/dist/primitives/overlay/PopoverTrigger.js +38 -0
  277. package/dist/primitives/overlay/Preview.d.ts +19 -0
  278. package/dist/primitives/overlay/Preview.js +60 -0
  279. package/dist/primitives/overlay/Tooltip.d.ts +38 -0
  280. package/dist/primitives/overlay/Tooltip.js +74 -0
  281. package/dist/primitives/overlay/index.d.ts +4 -0
  282. package/dist/primitives/overlay/index.js +7 -0
  283. package/dist/primitives/picker/Picker.d.ts +89 -0
  284. package/dist/primitives/picker/Picker.js +204 -0
  285. package/dist/primitives/picker/index.d.ts +1 -0
  286. package/dist/primitives/picker/index.js +2 -0
  287. package/dist/primitives/surface/Peek.d.ts +60 -0
  288. package/dist/primitives/surface/Peek.js +71 -0
  289. package/dist/primitives/surface/index.d.ts +1 -0
  290. package/dist/primitives/surface/index.js +2 -0
  291. package/dist/primitives/table/CellCopy.d.ts +20 -0
  292. package/dist/primitives/table/CellCopy.js +23 -0
  293. package/dist/primitives/table/CellEditor.d.ts +14 -0
  294. package/dist/primitives/table/CellEditor.js +83 -0
  295. package/dist/primitives/table/DataTable.d.ts +189 -0
  296. package/dist/primitives/table/DataTable.js +330 -0
  297. package/dist/primitives/table/EditableTable.d.ts +191 -0
  298. package/dist/primitives/table/EditableTable.js +617 -0
  299. package/dist/primitives/table/PivotTable.d.ts +14 -0
  300. package/dist/primitives/table/PivotTable.js +0 -0
  301. package/dist/primitives/table/ReportTable.d.ts +38 -0
  302. package/dist/primitives/table/ReportTable.js +106 -0
  303. package/dist/primitives/table/RowActions.d.ts +16 -0
  304. package/dist/primitives/table/RowActions.js +28 -0
  305. package/dist/primitives/table/SheetTable.d.ts +73 -0
  306. package/dist/primitives/table/SheetTable.js +230 -0
  307. package/dist/primitives/table/Table.d.ts +106 -0
  308. package/dist/primitives/table/Table.js +116 -0
  309. package/dist/primitives/table/index.d.ts +7 -0
  310. package/dist/primitives/table/index.js +9 -0
  311. package/dist/primitives/tabs/Tabs.d.ts +91 -0
  312. package/dist/primitives/tabs/Tabs.js +56 -0
  313. package/dist/primitives/tabs/index.d.ts +1 -0
  314. package/dist/primitives/tabs/index.js +1 -0
  315. package/dist/primitives/tag/Tag.d.ts +36 -0
  316. package/dist/primitives/tag/Tag.js +68 -0
  317. package/dist/primitives/tag/Tags.d.ts +57 -0
  318. package/dist/primitives/tag/Tags.js +104 -0
  319. package/dist/primitives/tag/TagsField.d.ts +35 -0
  320. package/dist/primitives/tag/TagsField.js +186 -0
  321. package/dist/primitives/tag/choices.d.ts +38 -0
  322. package/dist/primitives/tag/choices.js +26 -0
  323. package/dist/primitives/tag/index.d.ts +4 -0
  324. package/dist/primitives/tag/index.js +8 -0
  325. package/dist/primitives/toolbar/Toolbar.d.ts +13 -0
  326. package/dist/primitives/toolbar/Toolbar.js +36 -0
  327. package/dist/primitives/toolbar/index.d.ts +1 -0
  328. package/dist/primitives/toolbar/index.js +2 -0
  329. package/dist/primitives/tree/Tree.d.ts +56 -0
  330. package/dist/primitives/tree/Tree.js +74 -0
  331. package/dist/primitives/tree/index.d.ts +1 -0
  332. package/dist/primitives/tree/index.js +3 -0
  333. package/dist/primitives/value/Copyable.d.ts +48 -0
  334. package/dist/primitives/value/Copyable.js +71 -0
  335. package/dist/primitives/value/Fecha.d.ts +12 -0
  336. package/dist/primitives/value/Fecha.js +89 -0
  337. package/dist/primitives/value/Meter.d.ts +29 -0
  338. package/dist/primitives/value/Meter.js +46 -0
  339. package/dist/primitives/value/Metric.d.ts +42 -0
  340. package/dist/primitives/value/Metric.js +38 -0
  341. package/dist/primitives/value/Person.d.ts +90 -0
  342. package/dist/primitives/value/Person.js +208 -0
  343. package/dist/primitives/value/ProgressBar.d.ts +31 -0
  344. package/dist/primitives/value/ProgressBar.js +53 -0
  345. package/dist/primitives/value/Relation.d.ts +74 -0
  346. package/dist/primitives/value/Relation.js +74 -0
  347. package/dist/primitives/value/Totals.d.ts +121 -0
  348. package/dist/primitives/value/Totals.js +54 -0
  349. package/dist/primitives/value/Value.d.ts +40 -0
  350. package/dist/primitives/value/Value.js +80 -0
  351. package/dist/primitives/value/index.d.ts +9 -0
  352. package/dist/primitives/value/index.js +10 -0
  353. package/dist/tokens.css +1062 -0
  354. package/dist/views/index.d.ts +2 -0
  355. package/dist/views/index.js +3 -0
  356. package/dist/views/list/List.d.ts +119 -0
  357. package/dist/views/list/List.js +101 -0
  358. package/dist/views/list/ListView.d.ts +6 -0
  359. package/dist/views/list/ListView.js +295 -0
  360. package/dist/views/list/columns.d.ts +18 -0
  361. package/dist/views/list/columns.js +27 -0
  362. package/dist/views/list/derive.d.ts +87 -0
  363. package/dist/views/list/derive.js +207 -0
  364. package/dist/views/list/index.d.ts +2 -0
  365. package/dist/views/list/index.js +4 -0
  366. package/dist/views/list/presentations.d.ts +39 -0
  367. package/dist/views/list/presentations.js +105 -0
  368. package/dist/views/list/types.d.ts +284 -0
  369. package/dist/views/list/types.js +1 -0
  370. package/dist/views/list/useNarrowList.d.ts +17 -0
  371. package/dist/views/list/useNarrowList.js +32 -0
  372. package/dist/views/record/Record.d.ts +145 -0
  373. package/dist/views/record/Record.js +211 -0
  374. package/dist/views/record/index.d.ts +1 -0
  375. package/dist/views/record/index.js +2 -0
  376. package/package.json +113 -4
@@ -0,0 +1,77 @@
1
+ import { type UiCopy } from "../../foundations/copy.js";
2
+ import type { ToastSpec } from "../../primitives/notice/Toast.js";
3
+ import { type LucideIcon } from "lucide-react";
4
+ import type { ReactNode } from "react";
5
+ /** The one mark of the assistant, everywhere it appears: the suggestion, the review, the
6
+ * marker on a value, the event in the history. A robot and not sparkles — it says «an
7
+ * automated assistant did this», which is a fact, not a celebration.
8
+ *
9
+ * Exported so a screen that composes the assistant into a piece of its own — a `Callout`,
10
+ * a `ActivityEvent` — uses the same mark and not a second one. */
11
+ export declare const ASSIST_ICON: LucideIcon;
12
+ /** Where a suggestion or a change comes from: «orden de compra PO/2026/0042», «las últimas
13
+ * 5 facturas del cliente». With `href` it is a real link; with `onOpen`, a button that the
14
+ * screen answers. Without either it is said, not linked. */
15
+ export type AssistSource = {
16
+ label: string;
17
+ href?: string;
18
+ onOpen?: () => void;
19
+ };
20
+ /** What a value set by the assistant carries afterwards: when, from what, and who said yes. */
21
+ export type AssistOrigin = {
22
+ /** When the assistant set it (or when it was accepted). */
23
+ at?: Date | string | number;
24
+ source?: AssistSource;
25
+ /** The person who accepted it. The assistant proposes; a person decides. */
26
+ acceptedBy?: string;
27
+ };
28
+ /** Applying something the assistant proposed. It may return the function that reverts it:
29
+ * with one, the screen gets a «Deshacer» notice; without one, nothing to undo is offered. */
30
+ export type AssistApply<A extends unknown[] = []> = (...args: A) => (() => void) | void;
31
+ /** The part of the toast API the family uses — the optional toast hook gives it, or `null`. */
32
+ export type AssistToasts = {
33
+ show: (spec: ToastSpec) => number;
34
+ } | null;
35
+ /**
36
+ * Runs `apply` and, when it returns an undo and there is a notice stack, offers it.
37
+ *
38
+ * Context: undo over confirm (docs/PRINCIPLES.md §7). Accepting a suggestion does not ask
39
+ * «¿estás seguro?» — the change happens at once, and the notice carries the way back. The
40
+ * notice is `good` because the change worked; the undo lives in its action, which is the
41
+ * same «Deshacer» a removed line or a registered payment offers.
42
+ */
43
+ export declare function applyWithUndo(apply: () => (() => void) | void, toasts: AssistToasts, message: string, undoLabel: string): void;
44
+ /** The notice after accepting a suggestion — naming the field when the screen said which. */
45
+ export declare function acceptedMessage(copy: UiCopy, field?: string): string;
46
+ export type ChangeKind = "add" | "remove" | "change";
47
+ /** One proposed change, as plain data — what `ChangeReview.Change` is written with. */
48
+ export type ProposedChange = {
49
+ id: string;
50
+ /** What changes: the field's label, or the line's name. */
51
+ label: string;
52
+ /** The value now. Absent = the thing does not exist yet (`add`). `null` = an empty field. */
53
+ before?: ReactNode;
54
+ /** The value after. Absent = the thing goes away (`remove`). */
55
+ after?: ReactNode;
56
+ /** Forces the kind; by default it follows from `before` and `after`. */
57
+ kind?: ChangeKind;
58
+ /** A second line under the label: the product's code, «40 bolsas × Bs. 58,00». */
59
+ detail?: ReactNode;
60
+ /** Where THIS change comes from, when it is not the review's own source. */
61
+ source?: AssistSource;
62
+ /** Proposed but not chosen when the review opens — the assistant is less sure of it. */
63
+ unchosen?: boolean;
64
+ };
65
+ /** The kind of a change, from what it has: no `before` → new, no `after` → removed. */
66
+ export declare function changeKind(change: Pick<ProposedChange, "before" | "after" | "kind">): ChangeKind;
67
+ /** The ids chosen when a review opens: all of them but the ones marked `unchosen`. */
68
+ export declare function initiallyChosen(changes: readonly ProposedChange[]): string[];
69
+ /** Turns one change on or off, and returns the chosen ids IN THE ORDER the review lists
70
+ * them — so what `onApply` receives reads like the screen, not like the clicks. */
71
+ export declare function toggleChosen(order: readonly string[], chosen: readonly string[], id: string, on: boolean): string[];
72
+ /** Whether the «all» check is on, off, or mixed. */
73
+ export declare function chosenState(order: readonly string[], chosen: readonly string[]): "all" | "some" | "none";
74
+ /** The label of the apply button, with the count — a button that says how much it does. */
75
+ export declare function applyLabel(copy: UiCopy, count: number): string;
76
+ /** The notice after applying. */
77
+ export declare function appliedMessage(copy: UiCopy, count: number): string;
@@ -0,0 +1,87 @@
1
+ import { fillCopy } from "../../foundations/copy.js";
2
+ import { Bot } from "lucide-react";
3
+ /* ==================================================================== *
4
+ * THE ASSISTANT'S CONTRACT — what every piece of this family agrees on.
5
+ *
6
+ * An assistant that acts inside a business screen is trusted for one reason:
7
+ * whoever works the screen can always answer three questions about what it did.
8
+ *
9
+ * where did it get that? → a SOURCE, a link to the record it read
10
+ * what exactly will change? → the value, or the before → after
11
+ * how do I take it back? → apply returns its UNDO
12
+ *
13
+ * So a source is plain data (a label and where it goes), and applying anything
14
+ * — accepting a suggestion, applying a set of changes — is a function the
15
+ * screen writes and that RETURNS the function that reverts it. The family turns
16
+ * that return into the system's «Deshacer» notice; it never applies anything by
17
+ * itself, because it does not know what an invoice is.
18
+ *
19
+ * Pure on purpose (no hooks, no "use client"): the components call these, and
20
+ * the tests do too.
21
+ * ==================================================================== */
22
+ /** The one mark of the assistant, everywhere it appears: the suggestion, the review, the
23
+ * marker on a value, the event in the history. A robot and not sparkles — it says «an
24
+ * automated assistant did this», which is a fact, not a celebration.
25
+ *
26
+ * Exported so a screen that composes the assistant into a piece of its own — a `Callout`,
27
+ * a `ActivityEvent` — uses the same mark and not a second one. */
28
+ export const ASSIST_ICON = Bot;
29
+ /**
30
+ * Runs `apply` and, when it returns an undo and there is a notice stack, offers it.
31
+ *
32
+ * Context: undo over confirm (docs/PRINCIPLES.md §7). Accepting a suggestion does not ask
33
+ * «¿estás seguro?» — the change happens at once, and the notice carries the way back. The
34
+ * notice is `good` because the change worked; the undo lives in its action, which is the
35
+ * same «Deshacer» a removed line or a registered payment offers.
36
+ */
37
+ export function applyWithUndo(apply, toasts, message, undoLabel) {
38
+ const undo = apply();
39
+ if (typeof undo !== "function" || toasts === null)
40
+ return;
41
+ toasts.show({ message, tone: "good", action: { label: undoLabel, onSelect: undo } });
42
+ }
43
+ /** The notice after accepting a suggestion — naming the field when the screen said which. */
44
+ export function acceptedMessage(copy, field) {
45
+ return field === undefined
46
+ ? copy.assist.accepted
47
+ : fillCopy(copy.assist.acceptedIn, { field });
48
+ }
49
+ /** The kind of a change, from what it has: no `before` → new, no `after` → removed. */
50
+ export function changeKind(change) {
51
+ if (change.kind !== undefined)
52
+ return change.kind;
53
+ if (change.before === undefined)
54
+ return "add";
55
+ if (change.after === undefined)
56
+ return "remove";
57
+ return "change";
58
+ }
59
+ /** The ids chosen when a review opens: all of them but the ones marked `unchosen`. */
60
+ export function initiallyChosen(changes) {
61
+ return changes.filter((c) => c.unchosen !== true).map((c) => c.id);
62
+ }
63
+ /** Turns one change on or off, and returns the chosen ids IN THE ORDER the review lists
64
+ * them — so what `onApply` receives reads like the screen, not like the clicks. */
65
+ export function toggleChosen(order, chosen, id, on) {
66
+ const next = new Set(chosen);
67
+ if (on)
68
+ next.add(id);
69
+ else
70
+ next.delete(id);
71
+ return order.filter((one) => next.has(one));
72
+ }
73
+ /** Whether the «all» check is on, off, or mixed. */
74
+ export function chosenState(order, chosen) {
75
+ const count = order.filter((id) => chosen.includes(id)).length;
76
+ if (count === 0)
77
+ return "none";
78
+ return count === order.length ? "all" : "some";
79
+ }
80
+ /** The label of the apply button, with the count — a button that says how much it does. */
81
+ export function applyLabel(copy, count) {
82
+ return count === 1 ? copy.assist.applyOne : fillCopy(copy.assist.applyMany, { count });
83
+ }
84
+ /** The notice after applying. */
85
+ export function appliedMessage(copy, count) {
86
+ return count === 1 ? copy.assist.appliedOne : fillCopy(copy.assist.appliedMany, { count });
87
+ }
@@ -0,0 +1,5 @@
1
+ export { ASSIST_ICON, type AssistApply, type AssistOrigin, type AssistSource, type ChangeKind, type ProposedChange, } from "./assist.js";
2
+ export { AssistedValue, assistEvent, AssistLabel, AssistMark, type AssistMarkProps, AssistSourceLink, } from "./AssistMark.js";
3
+ export { AssistPending, type AssistPendingProps, } from "./AssistPending.js";
4
+ export { AssistSuggestion, type AssistSuggestionProps, } from "./AssistSuggestion.js";
5
+ export { ChangeReview, ChangeReviewDialog, type ChangeReviewDialogProps, type ChangeReviewProps, } from "./ChangeReview.js";
@@ -0,0 +1,7 @@
1
+ /* The assistant inside a business screen: a suggestion with its source, a preview of the
2
+ changes it proposes, the mark it leaves on what it set, and its working state. */
3
+ export { ASSIST_ICON, } from "./assist.js";
4
+ export { AssistedValue, assistEvent, AssistLabel, AssistMark, AssistSourceLink, } from "./AssistMark.js";
5
+ export { AssistPending, } from "./AssistPending.js";
6
+ export { AssistSuggestion, } from "./AssistSuggestion.js";
7
+ export { ChangeReview, ChangeReviewDialog, } from "./ChangeReview.js";
@@ -0,0 +1,52 @@
1
+ import type { Tone } from "../../foundations/types.js";
2
+ import type { ReactNode } from "react";
3
+ /** A group of fields with its name and its status.
4
+ *
5
+ * The `status` is the only thing worth copying from the old console: every
6
+ * section said `Required` or `(Incomplete)` in its header, so you could see
7
+ * **what was missing without opening any of them**. Our version forced you to
8
+ * go into every aspect to discover it was empty. */
9
+ export declare function FormSection({ title, hint, status, actions, columns, children, }: {
10
+ /** Absent when the surface already named the form — a dialog title is the
11
+ * section, and repeating «parámetros» under it is a second chrome. */
12
+ title?: string;
13
+ hint?: string;
14
+ /** Context: the tones are the system's and not two names of their own. `falta`
15
+ * and `listo` were a third scale of meaning that only existed here, and it
16
+ * forced you to translate it in order to paint the same pill. */
17
+ status?: {
18
+ label: string;
19
+ tone?: Tone;
20
+ };
21
+ /** The buttons of THIS section: "add a rule", "copy from the last order". They
22
+ * go in the header and not at the end: what goes at the end closes the whole
23
+ * form, and mixing them makes you doubt what saves what. */
24
+ actions?: ReactNode;
25
+ /** How many columns of fields. In compact it goes back to a single one without
26
+ * asking: two columns in 480 px are two half columns. Three is the ceiling —
27
+ * at the fourth, the label and the value no longer fit on the same line. */
28
+ columns?: 1 | 2 | 3;
29
+ children: ReactNode;
30
+ }): import("react").JSX.Element;
31
+ /** What closes a form. One primary, on the right.
32
+ *
33
+ * Cancel sits just to the left of that primary: the two answers to «what do
34
+ * I do with what I wrote». Destroy sits on the far left. Stuck to the
35
+ * primary, a stray click or an Enter lands on the thing that cannot be
36
+ * undone. The sentence, when there is one, stays with the destroy side —
37
+ * it is the warning, not a third button.
38
+ *
39
+ * Context: on a phone (below `sm`, the 40rem of `--container-handheld`) the bar sticks
40
+ * to the bottom of whatever scrolls the form —the window, or a bottom sheet's body— so
41
+ * the primary stays under the thumb while the fields go by, instead of waiting at the
42
+ * end of a form three screens long. Sticky and not fixed: it is the last thing in the
43
+ * form, so at the end it settles in its own place and covers nothing. On a desk it is
44
+ * exactly the static bar it always was. */
45
+ export declare function FormActions({ primary, secondary, danger, aside, }: {
46
+ primary: ReactNode;
47
+ secondary?: ReactNode;
48
+ /** Destroy. Far from the primary. Red belongs here, not on cancel. */
49
+ danger?: ReactNode;
50
+ /** What has to be said before pressing: "this cannot be undone". */
51
+ aside?: ReactNode;
52
+ }): import("react").JSX.Element;
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { byDensity, useDensity } from "../../foundations/density.js";
4
+ import { Hint } from "../../primitives/hint/Hint.js";
5
+ import { Tag } from "../../primitives/tag/Tag.js";
6
+ /* ==================================================================== *
7
+ * LA COMPOSICIÓN DE UN FORMULARIO: la sección y el pie.
8
+ *
9
+ * Vive en `contexts/form` y no junto a los controles porque no es un control:
10
+ * es lo que los ACOMODA. `TextInput` no sabe que existe un formulario —se usa
11
+ * igual adentro de una celda, de un filtro o de un diálogo— y una sección no
12
+ * sabe qué campos le van a poner adentro. Son dos capas y por eso son dos
13
+ * carpetas: `primitives/field` es CON QUÉ se escribe, esto es CÓMO se arma.
14
+ * ==================================================================== */
15
+ /** A group of fields with its name and its status.
16
+ *
17
+ * The `status` is the only thing worth copying from the old console: every
18
+ * section said `Required` or `(Incomplete)` in its header, so you could see
19
+ * **what was missing without opening any of them**. Our version forced you to
20
+ * go into every aspect to discover it was empty. */
21
+ export function FormSection({ title, hint, status, actions, columns = 1, children, }) {
22
+ const d = useDensity();
23
+ const asGrid = columns > 1 && d === "comfortable";
24
+ const grid = columns === 3 ? "grid-cols-3" : "grid-cols-2";
25
+ const withHeader = title !== undefined ||
26
+ status !== undefined ||
27
+ hint !== undefined ||
28
+ actions !== undefined;
29
+ return (_jsxs("section", { className: `flex min-w-0 flex-col ${byDensity(d, "gap-3", "gap-2")}`, children: [withHeader ? (_jsxs("header", { className: "flex min-w-0 flex-wrap items-center gap-x-2.5 gap-y-1", children: [title === undefined && hint === undefined ? null : (_jsxs("h3", { className: "flex min-w-0 items-center gap-1 text-meta font-medium text-ink", children: [title === undefined ? null : _jsx("span", { className: "min-w-0 truncate", children: title }), hint === undefined ? null : _jsx(Hint, { children: hint })] })), status === undefined ? null : _jsx(Tag, { tone: status.tone, children: status.label }), actions === undefined ? null : (_jsx("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: actions }))] })) : null, _jsx("div", { className: `min-w-0 ${asGrid
30
+ ? `grid ${grid} gap-x-8 ${byDensity(d, "gap-y-3.5", "gap-y-2.5")}`
31
+ : `flex flex-col ${byDensity(d, "gap-3.5", "gap-2.5")}`}`, children: children })] }));
32
+ }
33
+ /** What closes a form. One primary, on the right.
34
+ *
35
+ * Cancel sits just to the left of that primary: the two answers to «what do
36
+ * I do with what I wrote». Destroy sits on the far left. Stuck to the
37
+ * primary, a stray click or an Enter lands on the thing that cannot be
38
+ * undone. The sentence, when there is one, stays with the destroy side —
39
+ * it is the warning, not a third button.
40
+ *
41
+ * Context: on a phone (below `sm`, the 40rem of `--container-handheld`) the bar sticks
42
+ * to the bottom of whatever scrolls the form —the window, or a bottom sheet's body— so
43
+ * the primary stays under the thumb while the fields go by, instead of waiting at the
44
+ * end of a form three screens long. Sticky and not fixed: it is the last thing in the
45
+ * form, so at the end it settles in its own place and covers nothing. On a desk it is
46
+ * exactly the static bar it always was. */
47
+ export function FormActions({ primary, secondary, danger, aside, }) {
48
+ return (_jsxs("div", { "data-form-actions": "", className: "flex flex-wrap items-center gap-2 border-t border-line pt-3.5 max-sm:sticky max-sm:bottom-0 max-sm:z-10 max-sm:bg-surface max-sm:safe-bottom", children: [danger, aside === undefined ? null : (_jsx("span", { className: "min-w-0 text-micro text-muted", children: aside })), _jsxs("span", { className: "ml-auto flex items-center gap-2", children: [secondary, primary] })] }));
49
+ }
@@ -0,0 +1,47 @@
1
+ import { type SheetLayout } from "../../primitives/field/layout.js";
2
+ import { type FieldNote } from "../../primitives/field/note.js";
3
+ import type { LucideIcon } from "lucide-react";
4
+ import { type ReactNode } from "react";
5
+ export type { SheetLayout };
6
+ export type SheetField = {
7
+ label: string;
8
+ value: ReactNode;
9
+ /** Help on the label, as a `?`. Hover or click. */
10
+ hint?: string;
11
+ mono?: boolean;
12
+ /** A note that belongs to this fact — the same as `Field`'s: a flag by the label, and an
13
+ * entry in the record's activity. */
14
+ note?: FieldNote;
15
+ };
16
+ export declare function Sheet({ fields, columns, layout, head, children, }: {
17
+ fields?: readonly SheetField[];
18
+ columns?: 1 | 2 | 3 | 4;
19
+ /** How fields inside this sheet (and its groups) place the label. */
20
+ layout?: SheetLayout;
21
+ /** The top of the paper: groups, then the notebook sitting on its mouth.
22
+ * It shares a short gap with `fields`, so the tabs belong to the sheet
23
+ * and not to the page below. */
24
+ head?: ReactNode;
25
+ children?: ReactNode;
26
+ }): import("react").JSX.Element | null;
27
+ /** A row of columns on the paper. The paper is the sheet; a group is not a
28
+ * second box. A vertical hairline separates columns — that is what still
29
+ * groups them when a column has no title. */
30
+ export declare function SheetGroups({ children, columns, }: {
31
+ children: ReactNode;
32
+ columns?: 2 | 3 | 4;
33
+ }): import("react").JSX.Element;
34
+ /** One column of a `SheetGroups` row.
35
+ *
36
+ * The title is OPTIONAL. With one, it is a name above the fields — the same
37
+ * name in read and in edit, so the paper does not rearrange. Without one,
38
+ * the column is still a group: the hairline between columns is the edge.
39
+ *
40
+ * It is not a tray and not a card. Nested boxes on the sheet made untitled
41
+ * groups look empty and made edit mode look like a dashboard. */
42
+ export declare function SheetGroup({ title, hint, icon: Icon, children, }: {
43
+ title?: string;
44
+ hint?: string;
45
+ icon?: LucideIcon;
46
+ children: ReactNode;
47
+ }): import("react").JSX.Element;
@@ -0,0 +1,90 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { byDensity, useDensity } from "../../foundations/density.js";
4
+ import { FieldLayoutProvider, } from "../../primitives/field/layout.js";
5
+ import { NoteCard, NoteFlag } from "../../primitives/field/note.js";
6
+ import { Hint } from "../../primitives/hint/Hint.js";
7
+ import { Children, useId } from "react";
8
+ function Facts({ fields, columns, layout, }) {
9
+ const d = useDensity();
10
+ const idBase = useId();
11
+ const horizontal = layout === "horizontal";
12
+ /* Horizontal facts are a run of pairs, not a grid stretched across the
13
+ paper. A two-column grid put «Total Bs 12.480» on the left and «Vence
14
+ 15 nov» on the right, with the middle of the card empty. */
15
+ const asGrid = !horizontal && columns > 1 && d === "comfortable";
16
+ const grid = columns === 4
17
+ ? "grid-cols-2 @lg:grid-cols-4"
18
+ : columns === 3
19
+ ? "grid-cols-3"
20
+ : "grid-cols-2";
21
+ return (_jsx("dl", { className: horizontal
22
+ ? "flex min-w-0 flex-wrap items-baseline gap-x-6 gap-y-1.5"
23
+ : asGrid
24
+ ? `@container grid min-w-0 ${grid} ${byDensity(d, "gap-x-8 gap-y-2.5", "gap-x-6 gap-y-2")}`
25
+ : `flex min-w-0 flex-col ${byDensity(d, "gap-2.5", "gap-2")}`, children: fields.map((field, at) => {
26
+ const noteId = field.note === undefined ? undefined : `${idBase}-${at}-note`;
27
+ const empty = field.value === undefined || field.value === null || field.value === "";
28
+ const card = field.note === undefined || noteId === undefined ? null : (_jsx(NoteCard, { note: field.note, id: noteId, owner: field.label }));
29
+ /* The note's card goes INSIDE the value: a `<dl>` holds only its terms and values.
30
+ With a note the value is a flex box, so the absolute card keeps the value's top
31
+ as its static position while being read after it. */
32
+ const value = (_jsxs("dd", { ...(noteId === undefined ? {} : { "aria-describedby": noteId }), className: `min-w-0 text-meta ${card === null ? "" : "flex"} ${empty ? "text-muted italic" : "text-ink"} ${field.mono === true ? "font-mono tabular-nums" : ""}`, children: [empty ? "—" : field.value, card] }));
33
+ const name = (_jsxs("dt", { className: `flex items-center gap-1 text-micro text-muted ${horizontal ? "shrink-0" : "min-w-0"}`, children: [_jsx("span", { children: field.label }), field.hint === undefined ? null : _jsx(Hint, { children: field.hint }), field.note === undefined ? null : _jsx(NoteFlag, { note: field.note })] }));
34
+ if (horizontal) {
35
+ /* A header fact is a pair: the number sits next to its name. The
36
+ 8rem label column is for a form, where twenty values have to
37
+ start on the same vertical. Here it left «Filas» half a column
38
+ away from 400. */
39
+ return (_jsxs("div", { className: "flex min-w-0 items-baseline gap-2", children: [name, value] }, field.label));
40
+ }
41
+ return (_jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [name, value] }, field.label));
42
+ }) }));
43
+ }
44
+ export function Sheet({ fields, columns = 2, layout = "stacked", head, children, }) {
45
+ const d = useDensity();
46
+ const facts = fields !== undefined && fields.length > 0;
47
+ if (!facts && head === undefined && children === undefined)
48
+ return null;
49
+ const top = facts || head !== undefined ? (_jsxs("div", { className: `flex min-w-0 flex-col ${byDensity(d, "gap-4", "gap-3")}`, children: [facts ? _jsx(Facts, { fields: fields, columns: columns, layout: layout }) : null, head] })) : null;
50
+ return (_jsx(FieldLayoutProvider, { value: layout, children: _jsxs("div", { className: `flex min-w-0 flex-col ${byDensity(d, "gap-(--spacing-block)", "gap-2.5")}`, children: [top, children] }) }));
51
+ }
52
+ /** A row of columns on the paper. The paper is the sheet; a group is not a
53
+ * second box. A vertical hairline separates columns — that is what still
54
+ * groups them when a column has no title. */
55
+ export function SheetGroups({ children, columns = 2, }) {
56
+ const d = useDensity();
57
+ const stacked = d === "compact";
58
+ // Below `handheld` the columns stack the way compact density does: two 180 px
59
+ // columns on a phone left each label beside a control with no width at all. The
60
+ // container is a wrapper because a grid cannot query its own width.
61
+ const grid = stacked
62
+ ? "grid-cols-1"
63
+ : columns === 4
64
+ ? "grid-cols-2 @lg:grid-cols-4 @max-handheld:grid-cols-1"
65
+ : columns === 3
66
+ ? "grid-cols-3 @max-handheld:grid-cols-1"
67
+ : "grid-cols-2 @max-handheld:grid-cols-1";
68
+ const items = Children.toArray(children);
69
+ return (_jsx("div", { className: "@container min-w-0", children: _jsx("div", { className: `grid min-w-0 ${grid}`, children: items.map((child, i) => {
70
+ const first = i === 0;
71
+ const last = i === items.length - 1;
72
+ const edge = stacked
73
+ ? `${first ? "" : "border-t border-line pt-3"} ${last ? "" : "pb-3"}`
74
+ : `${first ? "" : "border-l border-line pl-6 @max-handheld:border-l-0 @max-handheld:border-t @max-handheld:pl-0 @max-handheld:pt-3"} ${last ? "" : "pr-6 @max-handheld:pr-0 @max-handheld:pb-3"}`;
75
+ return (_jsx("div", { className: `min-w-0 ${edge}`, children: child }, i));
76
+ }) }) }));
77
+ }
78
+ /** One column of a `SheetGroups` row.
79
+ *
80
+ * The title is OPTIONAL. With one, it is a name above the fields — the same
81
+ * name in read and in edit, so the paper does not rearrange. Without one,
82
+ * the column is still a group: the hairline between columns is the edge.
83
+ *
84
+ * It is not a tray and not a card. Nested boxes on the sheet made untitled
85
+ * groups look empty and made edit mode look like a dashboard. */
86
+ export function SheetGroup({ title, hint, icon: Icon, children, }) {
87
+ const d = useDensity();
88
+ const withHeader = title !== undefined;
89
+ return (_jsxs("section", { className: `flex min-w-0 flex-col ${byDensity(d, "gap-2.5", "gap-2")}`, children: [withHeader ? (_jsxs("header", { className: "flex min-w-0 items-center gap-2", children: [Icon === undefined ? null : (_jsx(Icon, { className: "size-(--size-icon-sm) shrink-0 text-muted", strokeWidth: 1.75, "aria-hidden": true })), _jsx("h3", { className: "min-w-0 truncate text-meta font-medium text-ink", children: title }), hint === undefined ? null : _jsx(Hint, { children: hint })] })) : hint === undefined ? null : (_jsx(Hint, { children: hint })), _jsx("div", { className: `flex min-w-0 flex-col ${byDensity(d, "gap-2.5", "gap-2")}`, children: children })] }));
90
+ }
@@ -0,0 +1,2 @@
1
+ export { FormActions, FormSection } from "./Form.js";
2
+ export { Sheet, type SheetField, SheetGroup, SheetGroups, type SheetLayout, } from "./Sheet.js";
@@ -0,0 +1,4 @@
1
+ /* FORMULARIO — lo que ACOMODA los campos: la hoja, la sección y el pie. Los
2
+ controles con los que se escribe están en `primitives/field`. */
3
+ export { FormActions, FormSection } from "./Form.js";
4
+ export { Sheet, SheetGroup, SheetGroups, } from "./Sheet.js";
@@ -0,0 +1,13 @@
1
+ import type { SeriesBar } from "./model.js";
2
+ /**
3
+ * One series, drawn as a bar list: the name, the count, and a track.
4
+ *
5
+ * A column of vertical bars with the names in a legend underneath asks the
6
+ * eye to match a bar to a word. Here the word sits on its own bar, which is
7
+ * the question this piece answers — how the values of one column are spread.
8
+ * CSS, not a charting library: the width is a percentage of the largest
9
+ * count, and the color is the data color, one series, not a palette.
10
+ */
11
+ export declare function SeriesChart({ series }: {
12
+ series: readonly SeriesBar[];
13
+ }): import("react").JSX.Element;
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useUiCopy } from "../../foundations/copy.js";
4
+ /**
5
+ * One series, drawn as a bar list: the name, the count, and a track.
6
+ *
7
+ * A column of vertical bars with the names in a legend underneath asks the
8
+ * eye to match a bar to a word. Here the word sits on its own bar, which is
9
+ * the question this piece answers — how the values of one column are spread.
10
+ * CSS, not a charting library: the width is a percentage of the largest
11
+ * count, and the color is the data color, one series, not a palette.
12
+ */
13
+ export function SeriesChart({ series }) {
14
+ const copy = useUiCopy();
15
+ const peak = Math.max(1, ...series.map((bar) => bar.count));
16
+ if (series.length === 0) {
17
+ return _jsx("p", { className: "px-3 py-4 text-body text-muted", children: copy.frame.noSeries });
18
+ }
19
+ return (_jsx("ul", { className: "flex flex-col gap-2.5 px-3 py-3", children: series.map((bar) => {
20
+ const width = Math.max((bar.count / peak) * 100, 2);
21
+ const count = bar.count.toLocaleString(copy.locale);
22
+ return (_jsxs("li", { className: "flex min-w-0 flex-col gap-1", title: `${bar.label}: ${count}`, children: [_jsxs("div", { className: "flex min-w-0 items-baseline justify-between gap-3", children: [_jsx("span", { className: "min-w-0 truncate text-meta text-ink", children: bar.label }), _jsx("span", { className: "shrink-0 text-micro tabular-nums text-muted", children: count })] }), _jsx("div", { className: "h-1.5 overflow-hidden rounded-pill bg-ink/8", children: _jsx("div", { className: "h-full rounded-pill bg-data", style: { width: `${width}%` } }) })] }, bar.label));
23
+ }) }));
24
+ }
@@ -0,0 +1,33 @@
1
+ import { type Frame, type FramePresent } from "./model.js";
2
+ import { type ListIdentity } from "../listing/ListingBar.js";
3
+ import { type Grouping } from "../../foundations/grouping.js";
4
+ import { type ReactNode } from "react";
5
+ export type FrameViewProps = {
6
+ frame: Frame;
7
+ identity?: ListIdentity;
8
+ caption?: ReactNode;
9
+ present?: FramePresent;
10
+ presents?: readonly FramePresent[];
11
+ onPresentChange?: (next: FramePresent) => void;
12
+ /** Which column the chart reads. Defaults to the first numeric, else the first. */
13
+ chartColumn?: string;
14
+ onChartColumnChange?: (id: string) => void;
15
+ visibleColumnIds?: readonly string[];
16
+ onVisibleColumnIdsChange?: (ids: readonly string[]) => void;
17
+ /** Search, filters, pagination: the same slots as a list. A frame inside a
18
+ * form is still a SET of rows, and a set without a narrowing line is a
19
+ * dump. Assembled by whoever holds the domain — this file does not know
20
+ * what a column name is. */
21
+ search?: ReactNode;
22
+ pagination?: ReactNode;
23
+ /**
24
+ * El agrupado, con el mismo contrato que usa la lista.
25
+ *
26
+ * Acá lo que se agrupa son ÍNDICES de fila y no registros: un marco es una
27
+ * matriz y sus filas no tienen identidad propia —son la fila 12 del archivo—,
28
+ * así que `T` es `number` y `of(fila, nivel)` lee la celda que corresponda. El
29
+ * contrato no cambia, que es exactamente la prueba de que no es restrictivo.
30
+ */
31
+ grouping?: Grouping<number>;
32
+ };
33
+ export declare function FrameView({ frame, identity, caption, present: presentProp, presents, onPresentChange, chartColumn: chartColumnProp, onChartColumnChange, visibleColumnIds, onVisibleColumnIdsChange, search, pagination, grouping, }: FrameViewProps): import("react").JSX.Element;
@@ -0,0 +1,125 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { SeriesChart } from "./Chart.js";
4
+ import { columnSeries, withColumns, } from "./model.js";
5
+ import { useColumnControl } from "../listing/columns.js";
6
+ import { ColumnsMenu, specsFromColumns, } from "../listing/ColumnsMenu.js";
7
+ import { Listing } from "../listing/Listing.js";
8
+ import { ListingBar } from "../listing/ListingBar.js";
9
+ import { ViewSwitcher } from "../listing/ViewSwitcher.js";
10
+ import { useUiCopy } from "../../foundations/copy.js";
11
+ import { pathKey, pileIsOpen, pilesOf, } from "../../foundations/grouping.js";
12
+ import { Menu } from "../../primitives/menu/Menu.js";
13
+ import { Empty } from "../../primitives/notice/Notice.js";
14
+ import { SheetTable } from "../../primitives/table/SheetTable.js";
15
+ import { BarChart3, Table2 } from "lucide-react";
16
+ import { useMemo, useState } from "react";
17
+ /**
18
+ * ARCHETYPE 3 — a FRAME: the cells of a payload, as a table or as a chart.
19
+ *
20
+ * Context: ListView is N records of a kind. Record is ONE record. Neither
21
+ * is the glance at the raw matrix an imported file carries — that was being drawn as
22
+ * a naked SheetTable, so it could not change presentation, hide a column or
23
+ * chart one, which is exactly what looking at a table is for.
24
+ *
25
+ * Columns use the same `useColumnControl` as ListView. Payload columns default
26
+ * to optional; pin one with `optional: false`.
27
+ *
28
+ * The app maps a preview (or any rectangle) onto a `Frame`. This archetype
29
+ * does not know what an invoice is.
30
+ */
31
+ const PRESENT_ICONS = [
32
+ { id: "table", icon: Table2 },
33
+ { id: "chart", icon: BarChart3 },
34
+ ];
35
+ export function FrameView({ frame, identity, caption, present: presentProp, presents = ["table", "chart"], onPresentChange, chartColumn: chartColumnProp, onChartColumnChange, visibleColumnIds, onVisibleColumnIdsChange, search, pagination, grouping, }) {
36
+ const copy = useUiCopy();
37
+ const [ownedPresent, setOwnedPresent] = useState(presentProp ?? "table");
38
+ const present = onPresentChange !== undefined ? (presentProp ?? "table") : ownedPresent;
39
+ const setPresent = onPresentChange ?? setOwnedPresent;
40
+ const defaultChart = frame.columns.find((column) => column.numeric)?.id ?? frame.columns[0]?.id ?? "";
41
+ const [ownedChart, setOwnedChart] = useState(chartColumnProp ?? defaultChart);
42
+ const chartColumn = onChartColumnChange !== undefined ? (chartColumnProp ?? defaultChart) : ownedChart;
43
+ const setChartColumn = onChartColumnChange ?? setOwnedChart;
44
+ const columnSpecs = useMemo(() => specsFromColumns(frame.columns, true), [frame.columns]);
45
+ const columns = useColumnControl(columnSpecs, {
46
+ ...(visibleColumnIds === undefined ? {} : { visibleIds: visibleColumnIds }),
47
+ ...(onVisibleColumnIdsChange === undefined ? {} : { onVisibleColumnIdsChange }),
48
+ });
49
+ const shown = useMemo(() => columns.visibleIds.length === frame.columns.length
50
+ ? frame
51
+ : withColumns(frame, columns.visibleIds), [frame, columns.visibleIds]);
52
+ /* Los montones aplanados a una SECUENCIA: la planilla está virtualizada por
53
+ índice, así que la jerarquía la dice la sangría de cada banda y no el
54
+ anidamiento. Es el mismo aplanado que hace la lista, sobre índices en vez de
55
+ registros. */
56
+ const bands = useMemo(() => {
57
+ const piles = pilesOf(Array.from({ length: shown.rows }, (_, index) => index), grouping);
58
+ if (piles === null)
59
+ return null;
60
+ const out = [];
61
+ const walk = (list) => {
62
+ for (const pile of list) {
63
+ const open = pileIsOpen(pile, grouping);
64
+ out.push({
65
+ band: {
66
+ field: pile.field,
67
+ label: pile.label,
68
+ count: pile.count,
69
+ open,
70
+ depth: pile.depth,
71
+ key: pathKey(pile.path),
72
+ },
73
+ });
74
+ if (!open)
75
+ continue;
76
+ if (pile.piles.length > 0)
77
+ walk(pile.piles);
78
+ else
79
+ for (const row of pile.items)
80
+ out.push({ row });
81
+ }
82
+ };
83
+ walk(piles);
84
+ return out;
85
+ }, [shown.rows, grouping]);
86
+ const series = useMemo(() => (present === "chart" ? columnSeries(shown, chartColumn) : []), [present, shown, chartColumn]);
87
+ const switcher = presents.length > 1 ? (_jsx(ViewSwitcher, { options: PRESENT_ICONS.filter((option) => presents.includes(option.id)).map((option) => ({
88
+ id: option.id,
89
+ label: option.id === "table" ? copy.present.table : copy.present.chart,
90
+ icon: option.icon,
91
+ })), current: present, onSelect: (id) => setPresent(id) })) : undefined;
92
+ const chartMenu = present === "chart" ? (_jsx(Menu, { label: copy.frame.series, groups: [
93
+ {
94
+ label: copy.frame.column,
95
+ options: shown.columns.map((column) => ({
96
+ id: column.id,
97
+ label: column.type === undefined
98
+ ? column.header
99
+ : `${column.header} · ${column.type}`,
100
+ checked: column.id === chartColumn,
101
+ })),
102
+ },
103
+ ], onSelect: setChartColumn })) : null;
104
+ const bar = (_jsx(ListingBar, { ...(identity?.title === undefined ? {} : { title: identity.title }), ...(identity?.description === undefined ? {} : { description: identity.description }), ...(identity?.counters === undefined ? {} : { counters: identity.counters }), ...(search === undefined ? {} : { search }), ...(pagination === undefined ? {} : { pagination }), views: _jsxs(_Fragment, { children: [_jsx(ColumnsMenu, { control: columns }), chartMenu, switcher] }) }));
105
+ if (frame.rows === 0 || frame.columns.length === 0) {
106
+ return (_jsx(Listing, { bar: bar, children: _jsx(Empty, { sentence: copy.frame.empty }) }));
107
+ }
108
+ return (_jsx(Listing, { bar: bar, children: present === "chart" ? (_jsx(SeriesChart, { series: series })) : (_jsx(SheetTable, { columns: shown.columns, rows: bands === null ? shown.rows : bands.length, value: (index, column, columnIndex) => {
109
+ const row = bands === null ? index : bands[index]?.row;
110
+ return row === undefined ? null : shown.value(row, column, columnIndex);
111
+ }, height: "auto", ...(bands === null
112
+ ? {}
113
+ : {
114
+ band: (index) => bands[index]?.band,
115
+ ...(grouping?.onToggle === undefined
116
+ ? {}
117
+ : {
118
+ onBandToggle: (index) => {
119
+ const key = bands[index]?.band?.key;
120
+ if (key !== undefined)
121
+ grouping.onToggle?.(key);
122
+ },
123
+ }),
124
+ }), ...(caption === undefined ? {} : { caption }) })) }));
125
+ }
@@ -0,0 +1,3 @@
1
+ export { SeriesChart } from "./Chart.js";
2
+ export { FrameView, type FrameViewProps } from "./FrameView.js";
3
+ export { columnSeries, type Frame, type FrameCell, type FrameColumn, frameFromRows, type FramePresent, type SeriesBar, withColumns, } from "./model.js";