@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,121 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { appliedMessage, applyLabel, applyWithUndo, changeKind, chosenState, initiallyChosen, toggleChosen, } from "./assist.js";
4
+ import { AssistLabel, AssistSourceLink } from "./AssistMark.js";
5
+ import { fillCopy, useUiCopy } from "../../foundations/copy.js";
6
+ import { flatten, propsOf, slot, slotOf } from "../../foundations/slots.js";
7
+ import { Button } from "../../primitives/button/Button.js";
8
+ import { Dialog } from "../../primitives/dialog/Dialog.js";
9
+ import { Checkbox } from "../../primitives/field/Checks.js";
10
+ import { useToastIfAny } from "../../primitives/notice/Toast.js";
11
+ import { Tag } from "../../primitives/tag/Tag.js";
12
+ import { ArrowRight } from "lucide-react";
13
+ import { useId, useState } from "react";
14
+ const Group = slot("group", (_props) => null);
15
+ const Change = slot("change", (_props) => null);
16
+ /** The groups as written. Changes written outside a group form an untitled one in their
17
+ * place, so a short review is just its changes. */
18
+ function readTree(children) {
19
+ const out = [];
20
+ let loose = null;
21
+ for (const node of flatten(children)) {
22
+ const name = slotOf(node);
23
+ if (name === "group") {
24
+ loose = null;
25
+ const props = propsOf(node);
26
+ out.push({
27
+ ...(props.title === undefined ? {} : { title: props.title }),
28
+ changes: flatten(props.children)
29
+ .filter((one) => slotOf(one) === "change")
30
+ .map((one) => propsOf(one)),
31
+ });
32
+ }
33
+ else if (name === "change") {
34
+ if (loose === null) {
35
+ loose = { changes: [] };
36
+ out.push(loose);
37
+ }
38
+ loose.changes.push(propsOf(node));
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+ /** What both faces share: the tree read once, the chosen ids, and «apply». */
44
+ function useReview({ children, chosen, onChosenChange, onApply }) {
45
+ const copy = useUiCopy();
46
+ const toasts = useToastIfAny();
47
+ const groups = readTree(children);
48
+ const all = groups.flatMap((g) => g.changes);
49
+ const order = all.map((c) => c.id);
50
+ const [own, setOwn] = useState(() => initiallyChosen(all));
51
+ const current = chosen === undefined ? own : order.filter((id) => chosen.includes(id));
52
+ const choose = (next) => {
53
+ if (chosen === undefined)
54
+ setOwn(next);
55
+ onChosenChange?.(next);
56
+ };
57
+ const apply = () => {
58
+ const ids = current;
59
+ applyWithUndo(() => onApply(ids), toasts, appliedMessage(copy, ids.length), copy.assist.undo);
60
+ };
61
+ return { groups, order, current, choose, apply };
62
+ }
63
+ /** One change: its check (named by its label), the kind in words, and before → after. */
64
+ function ChangeRow({ change, on, onToggle, }) {
65
+ const copy = useUiCopy();
66
+ const valuesId = useId();
67
+ const kind = changeKind(change);
68
+ const word = {
69
+ add: copy.assist.added,
70
+ remove: copy.assist.removed,
71
+ change: copy.assist.changed,
72
+ }[kind];
73
+ const empty = _jsx("span", { className: "text-muted italic", children: copy.assist.empty });
74
+ const before = change.before === null ? empty : change.before;
75
+ return (_jsxs("li", { "data-change": kind, className: "flex min-w-0 flex-col gap-1 border-b border-line px-4 py-2.5 last:border-b-0 @lg:flex-row @lg:items-start @lg:gap-4", children: [_jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsxs("span", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [_jsx(Checkbox, { checked: on, onChange: onToggle, label: change.label, describedBy: valuesId }), _jsx(Tag, { children: word })] }), change.detail === undefined ? null : (_jsx("span", { className: "pl-6.5 text-micro text-muted", children: change.detail })), change.source === undefined ? null : (_jsx("span", { className: "pl-6.5", children: _jsx(AssistSourceLink, { source: change.source }) }))] }), _jsxs("span", { id: valuesId, className: "flex min-w-0 flex-wrap items-baseline gap-x-1.5 pl-6.5 text-meta tabular-nums @lg:w-2/5 @lg:shrink-0 @lg:justify-end @lg:pl-0 @lg:text-right", children: [kind === "add" ? null : (_jsxs(_Fragment, { children: [_jsxs("span", { className: "sr-only", children: [copy.assist.from, " "] }), _jsx("span", { className: `text-muted ${kind === "remove" ? "line-through" : ""}`, children: before })] })), kind === "remove" ? null : (_jsxs(_Fragment, { children: [kind === "add" ? null : (_jsx(ArrowRight, { className: "size-(--size-icon-sm) shrink-0 self-center text-muted", strokeWidth: 2, "aria-hidden": true })), _jsxs("span", { className: "sr-only", children: [copy.assist.to, " "] }), _jsx("span", { className: "font-medium text-ink", children: change.after })] }))] })] }));
76
+ }
77
+ /** «Todos los cambios», the count, and the groups. */
78
+ function ReviewBody({ review }) {
79
+ const copy = useUiCopy();
80
+ const { groups, order, current, choose } = review;
81
+ const state = chosenState(order, current);
82
+ return (_jsxs("div", { className: "@container flex min-w-0 flex-col", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center justify-between gap-x-3 gap-y-1 border-b border-line px-4 py-2", children: [_jsx(Checkbox, { checked: state === "all", mixed: state === "some", label: copy.assist.all, onChange: (on) => choose(on ? [...order] : []) }), _jsx("span", { className: "text-micro text-muted tabular-nums", children: fillCopy(copy.assist.chosen, { count: current.length, total: order.length }) })] }), groups.map((group, i) => (_jsxs("section", { className: "flex min-w-0 flex-col", children: [group.title === undefined ? null : (_jsx("h4", { className: "px-4 pt-3 pb-1 text-micro font-medium text-muted", children: group.title })), _jsx("ul", { className: "flex min-w-0 flex-col", children: group.changes.map((change) => (_jsx(ChangeRow, { change: change, on: current.includes(change.id), onToggle: (on) => choose(toggleChosen(order, current, change.id, on)) }, change.id))) })] }, group.title ?? i)))] }));
83
+ }
84
+ /** «Elegí al menos un cambio.», «Descartar» and «Aplicar N cambios». */
85
+ function ReviewActions({ review, emphasis, onDiscard, after, }) {
86
+ const copy = useUiCopy();
87
+ const count = review.current.length;
88
+ return (_jsxs(_Fragment, { children: [count > 0 ? null : (
89
+ /* The reason next to the disabled button: a grey «Aplicar» with no explanation is a
90
+ dead end (the same rule as the wizard's «siguiente»). */
91
+ _jsx("span", { className: "mr-auto min-w-0 text-micro text-warn", children: copy.assist.noneChosen })), _jsx(Button, { role: "ghost", size: "sm", onClick: () => {
92
+ onDiscard();
93
+ after?.();
94
+ }, children: copy.assist.discard }), _jsx(Button, { role: emphasis, size: "sm", disabled: count === 0, onClick: () => {
95
+ review.apply();
96
+ after?.();
97
+ }, children: applyLabel(copy, count) })] }));
98
+ }
99
+ /** The review inside the page: a dashed card in the record it would change. */
100
+ export function ChangeReview(props) {
101
+ const { title, summary, source, onDiscard, emphasis = "primary" } = props;
102
+ const copy = useUiCopy();
103
+ const review = useReview(props);
104
+ const titleId = useId();
105
+ return (_jsxs("section", { "aria-labelledby": titleId, "data-assist": "review", className: "flex min-w-0 flex-col overflow-clip rounded-box border border-dashed border-info/40 bg-surface", children: [_jsxs("header", { className: "flex min-w-0 flex-col gap-1 border-b border-line px-4 py-3", children: [_jsxs("span", { className: "flex min-w-0 flex-wrap items-baseline gap-x-3 gap-y-1", children: [_jsx(AssistLabel, {}), source === undefined ? null : _jsx(AssistSourceLink, { source: source })] }), _jsx("h3", { id: titleId, className: "text-lead font-semibold text-ink", children: title ?? copy.assist.review }), summary === undefined ? null : (_jsx("p", { className: "max-w-prose text-meta text-muted", children: summary }))] }), _jsx(ReviewBody, { review: review }), _jsx("footer", { className: "flex min-w-0 flex-wrap items-center justify-end gap-2 border-t border-line bg-ground px-4 py-2.5", children: _jsx(ReviewActions, { review: review, emphasis: emphasis, onDiscard: onDiscard }) })] }));
106
+ }
107
+ ChangeReview.Group = Group;
108
+ ChangeReview.Change = Change;
109
+ /**
110
+ * The same review, in a `Dialog`: opened on demand — from a notice that says «el asistente
111
+ * encontró la orden de compra» — and a bottom sheet on a phone. «Aplicar» is the dialog's
112
+ * primary; closing without choosing keeps the proposal for later.
113
+ */
114
+ export function ChangeReviewDialog(props) {
115
+ const { open, onClose, context, title, summary, source, onDiscard } = props;
116
+ const copy = useUiCopy();
117
+ const review = useReview(props);
118
+ return (_jsx(Dialog, { open: open, onClose: onClose, title: title ?? copy.assist.review, ...(summary === undefined ? {} : { subtitle: summary }), ...(context === undefined ? {} : { context }), footer: _jsx(ReviewActions, { review: review, emphasis: "primary", onDiscard: onDiscard, after: onClose }), children: _jsxs("div", { className: "-mx-4 -my-4 flex min-w-0 flex-col", children: [_jsxs("span", { className: "flex min-w-0 flex-wrap items-baseline gap-x-3 gap-y-1 border-b border-line px-4 py-2.5", children: [_jsx(AssistLabel, {}), source === undefined ? null : _jsx(AssistSourceLink, { source: source })] }), _jsx(ReviewBody, { review: review })] }) }));
119
+ }
120
+ ChangeReviewDialog.Group = Group;
121
+ ChangeReviewDialog.Change = Change;
@@ -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 `ChatterEvent` — 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 `ChatterEvent` — 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,161 @@
1
+ import type { Message } from "./Messages.js";
2
+ import type { Tone } from "../../foundations/types.js";
3
+ import type { LucideIcon } from "lucide-react";
4
+ import { type ReactNode } from "react";
5
+ /**
6
+ * What a record has been through: what the system logged and what people wrote,
7
+ * in one place.
8
+ *
9
+ * Odoo calls it the chatter and the idea is the one worth taking: a record's
10
+ * history is not one more section of the record — it is the CONTEXT for
11
+ * everything else on the screen. Reading «the assessment failed» while looking
12
+ * at the inputs that produced it is the whole point.
13
+ *
14
+ * ── The merge is the default, and that is the decision ──────────────
15
+ *
16
+ * **Everything together comes first**, because the question somebody actually
17
+ * has is «what happened here», not «what happened here *according to the
18
+ * system*». A payment that bounced and the message somebody left about it are one
19
+ * story; splitting them by who wrote them makes the reader join them back by
20
+ * hand, comparing two timestamps in two lists.
21
+ *
22
+ * The other two tabs are for when you already know which half you want: «who
23
+ * said what» and «what ran». They are a narrowing of the first, never a
24
+ * different content.
25
+ *
26
+ * ── Why the tabs live HERE and not in whoever composes ──────────────
27
+ *
28
+ * They used to be a generic `tabs` array and every screen decided its own: same
29
+ * component, a different chatter on each record. What a record has been through
30
+ * is the same question everywhere, so the answer is the component's, not the
31
+ * screen's. The screen passes what it HAS —messages, events, a composer— and
32
+ * this decides how it is read.
33
+ *
34
+ * A tab with no source behind it is not drawn: with only events there is
35
+ * nothing to merge and nothing to separate, so it shows the stream and no tab
36
+ * bar at all.
37
+ *
38
+ * ── Cut into pages, like any other list ─────────────────────────────
39
+ *
40
+ * A record with six months behind it has hundreds of entries, and a column that
41
+ * only scrolls turns the history into something you give up on. The pages are
42
+ * this component's and not the screen's for the same reason the tabs are: it is
43
+ * the same list on every record.
44
+ *
45
+ * ── Beside on a wide panel, underneath on a narrow one ──────────────
46
+ *
47
+ * It asks `@container`, not `lg:`, for the reason `SectionGrid` already wrote
48
+ * down: with four panels open each one measures 380 px on a 1.600 screen, and a
49
+ * window rule would put a 22rem column inside a 380 px panel. **Whoever mounts
50
+ * it has to declare `@container` on the container** — `Record` does.
51
+ */
52
+ /**
53
+ * Algo que el sistema anotó.
54
+ *
55
+ * Deliberadamente NO es el evento del producto: lo que una historia necesita
56
+ * para dibujar uno es qué pasó, cuándo, quién, y —cuando las hay— las tres cosas
57
+ * que uno termina yendo a buscar a otro lado.
58
+ *
59
+ * ── Las tres que faltaban, y por qué cada una ───────────────────────
60
+ *
61
+ * by QUIÉN. «se publicó la factura» no dice si la publicó una persona o un
62
+ * cron, y esa es la primera pregunta cuando algo cambió sin aviso.
63
+ * Ausente = lo hizo el sistema, que también es una respuesta.
64
+ *
65
+ * moved DE QUÉ A QUÉ. «el proyecto cambió de estado» obliga a mirar el
66
+ * evento anterior para saber de dónde venía. «borrador →
67
+ * confirmado» se lee de una y es la línea más útil de una historia
68
+ * de gestión.
69
+ *
70
+ * error QUÉ falló, entero y textual. Un evento rojo que dice «falló» sin
71
+ * decir por qué manda a alguien a los logs — y quien mira esta
72
+ * pantalla muchas veces no tiene acceso a los logs.
73
+ */
74
+ export type ChatterEvent = {
75
+ id: string;
76
+ /** Qué pasó, en una oración y en pasado. */
77
+ label: ReactNode;
78
+ at: Date | string | number;
79
+ tone?: Tone;
80
+ /** Quién lo hizo. Ausente = el sistema. */
81
+ by?: string;
82
+ /** El cambio de estado, cuando lo hubo. `from` ausente = nació así. */
83
+ moved?: {
84
+ from?: string;
85
+ to: string;
86
+ };
87
+ /** Lo que hay que saber además del título, cuando el título no alcanza. */
88
+ detail?: ReactNode;
89
+ /** Lo que falló, textual. Se muestra la PRIMERA línea y el resto se abre: un
90
+ * stack de cuarenta renglones adentro de una historia tapa la historia, y lo
91
+ * que casi siempre alcanza es el primer renglón. */
92
+ error?: string;
93
+ /** El ícono del punto, cuando el tono no dice lo suficiente. Sin esto sale del
94
+ * tono, que es lo que evita un evento rojo con un tilde verde adentro. */
95
+ icon?: LucideIcon;
96
+ };
97
+ export type ChatterProps = {
98
+ /** What people wrote. Absent —not empty— while there is no service behind it:
99
+ * an empty thread says «nobody wrote yet», which is a different claim. */
100
+ messages?: readonly Message[];
101
+ /** What the system logged. */
102
+ events?: readonly ChatterEvent[];
103
+ /** The box to write in, when this record takes messages. It stays on top of
104
+ * the stream: writing is the thing you came to do, reading is what you do
105
+ * next. */
106
+ composer?: ReactNode;
107
+ /** Which tab is showing. Uncontrolled from «everything» when absent. */
108
+ current?: ChatterView;
109
+ onCurrentChange?: (next: ChatterView) => void;
110
+ open: boolean;
111
+ onToggle: () => void;
112
+ label?: string;
113
+ /** Dentro de la hoja del registro: no lleva marco propio, la hoja ya lo
114
+ * tiene. Sin esto es una tarjeta, que es como se ve cuando vive solo. */
115
+ embedded?: boolean;
116
+ /**
117
+ * Dónde vive el chatter respecto del registro.
118
+ *
119
+ * page DEBAJO y a TODO EL ANCHO, como una hoja propia. **Es el
120
+ * default**, y no por comodidad: un formulario necesita su ancho
121
+ * para que los campos no se apilen, y el de al costado se lo come
122
+ * en cuanto la pantalla no sobra. Abajo, la conversación no compite
123
+ * con el registro — es la otra mitad de la página.
124
+ * aside AL COSTADO cuando hay ancho, DEBAJO cuando no. Es para un
125
+ * registro que se LEE más de lo que se edita, donde tener la
126
+ * historia a la vista mientras se mira el dato vale el ancho que
127
+ * cuesta.
128
+ *
129
+ * La diferencia no es cosmética. En `aside` el ancho es escaso, así que el
130
+ * mensaje se lee en una columna de veintipico de caracteres; en `page` hay
131
+ * ancho de sobra y el texto se acota a una medida legible en vez de estirarse
132
+ * de punta a punta, que es donde un párrafo deja de poder seguirse.
133
+ *
134
+ * **Plegar es de pantalla chica.** En `page` el chatter no se pliega cuando
135
+ * hay ancho: plegarlo ahí esconde media pantalla para no ganar nada.
136
+ */
137
+ layout?: ChatterLayout;
138
+ };
139
+ export type ChatterLayout = "aside" | "page";
140
+ export type ChatterView = "all" | "messages" | "events";
141
+ export declare function Chatter({ messages, events, composer, current, onCurrentChange, open, onToggle, label: ownLabel, layout, embedded, }: ChatterProps): import("react").JSX.Element;
142
+ /** Whether the chatter is open, when the page has no better answer.
143
+ *
144
+ * **Starts folded.** It began the other way round —a history nobody opens is a
145
+ * history nobody reads— and seeing it took the argument apart: open, it holds a
146
+ * 22rem column of context on every record you open, before anybody asked for
147
+ * any. Folded it still says how many there are, which is the half that has to
148
+ * be free; reading them is a click, and a click you chose.
149
+ *
150
+ * It is the same answer for both layouts. A default that depends on the width
151
+ * would mean the same record shows a different screen depending on how many
152
+ * panels happen to be open next to it, and that is not a default, it is a
153
+ * surprise. */
154
+ export declare function useChatter(initial?: boolean): {
155
+ open: boolean;
156
+ toggle: () => void;
157
+ /** Open it without closing it if it already was. What a button from outside
158
+ * needs —«events 12»— when pressing it twice must not hide the very thing
159
+ * it promised to show. */
160
+ show: () => void;
161
+ };