@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,61 @@
1
+ import { composeClasses } from "../../foundations/variants.js";
2
+ import type { Ref } from "react";
3
+ import { type ButtonProps as AriaButtonProps, type GroupProps } from "react-aria-components";
4
+ /**
5
+ * The pieces every React Aria control of the system is built from — the box a date field,
6
+ * a combobox or a number field draws, and the small button inside it.
7
+ *
8
+ * Context: they look exactly like `controlClasses()` — same height, border, radius and
9
+ * focus — because a form mixes both kinds of control in one column, and a date field one
10
+ * pixel taller than the text input above it is the first thing an eye catches.
11
+ */
12
+ export declare const fieldGroupStyles: import("tailwind-variants/config").TVReturnType<{
13
+ isFocusWithin: {
14
+ false: string;
15
+ true: string;
16
+ };
17
+ isInvalid: {
18
+ true: string;
19
+ };
20
+ isDisabled: {
21
+ true: string;
22
+ };
23
+ }, undefined, "group flex h-(--size-control-md) w-full min-w-0 items-center overflow-hidden rounded-control border bg-surface text-meta text-ink transition-colors duration-(--duration-instant) forced-colors:bg-[Field]", {
24
+ isFocusVisible: {
25
+ false: string;
26
+ true: string;
27
+ };
28
+ }, undefined, import("tailwind-variants/config").TVReturnType<{
29
+ isFocusVisible: {
30
+ false: string;
31
+ true: string;
32
+ };
33
+ }, undefined, "outline-primary outline-offset-2 forced-colors:outline-[Highlight]", undefined, undefined, undefined>>;
34
+ /** The box of a composite control: a field and its buttons, framed as one input. The `ref`
35
+ * reaches the box (React 19: a plain prop) — a control that floats a list as wide as the
36
+ * box, like `TagsField`, measures it. */
37
+ export declare function FieldGroup({ ref, ...props }: GroupProps & {
38
+ ref?: Ref<HTMLDivElement>;
39
+ }): import("react").JSX.Element;
40
+ /** The button inside a field: the calendar of a date picker, the arrow of a combobox. */
41
+ export declare function FieldButton(props: AriaButtonProps): import("react").JSX.Element;
42
+ /**
43
+ * One row of a floating list — the options of a `Select`, the suggestions of a `Suggest`.
44
+ *
45
+ * Context: the same row `ComboBox` draws (control height, the `primary` tint on the row the
46
+ * keyboard is on), so every list that drops from a field reads as one kind of thing whatever
47
+ * control opened it.
48
+ */
49
+ export declare const listOptionStyles: import("tailwind-variants/config").TVReturnType<{
50
+ isFocused: {
51
+ true: string;
52
+ };
53
+ isPressed: {
54
+ true: string;
55
+ };
56
+ isDisabled: {
57
+ true: string;
58
+ };
59
+ }, undefined, "group flex min-h-(--size-control-md) cursor-default items-center gap-2 rounded-control px-2 py-1 text-meta text-ink outline-0 select-none forced-color-adjust-none", undefined, undefined, undefined>;
60
+ /** For a control that only adds to the system's classes. */
61
+ export { composeClasses };
@@ -0,0 +1,70 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { composeClasses, focusRing, tv } from "../../foundations/variants.js";
4
+ import { Button as AriaButton, composeRenderProps, Group, } from "react-aria-components";
5
+ /**
6
+ * The pieces every React Aria control of the system is built from — the box a date field,
7
+ * a combobox or a number field draws, and the small button inside it.
8
+ *
9
+ * Context: they look exactly like `controlClasses()` — same height, border, radius and
10
+ * focus — because a form mixes both kinds of control in one column, and a date field one
11
+ * pixel taller than the text input above it is the first thing an eye catches.
12
+ */
13
+ export const fieldGroupStyles = tv({
14
+ extend: focusRing,
15
+ base: "group flex h-(--size-control-md) w-full min-w-0 items-center overflow-hidden rounded-control border bg-surface text-meta text-ink transition-colors duration-(--duration-instant) forced-colors:bg-[Field]",
16
+ variants: {
17
+ isFocusWithin: {
18
+ false: "border-line-strong forced-colors:border-[ButtonBorder]",
19
+ true: "border-primary forced-colors:border-[Highlight]",
20
+ },
21
+ isInvalid: {
22
+ true: "border-danger forced-colors:border-[Mark]",
23
+ },
24
+ isDisabled: {
25
+ true: "cursor-not-allowed bg-ground text-muted forced-colors:border-[GrayText]",
26
+ },
27
+ },
28
+ });
29
+ /** The box of a composite control: a field and its buttons, framed as one input. The `ref`
30
+ * reaches the box (React 19: a plain prop) — a control that floats a list as wide as the
31
+ * box, like `TagsField`, measures it. */
32
+ export function FieldGroup({ ref, ...props }) {
33
+ return (_jsx(Group, { ref: ref, ...props, className: composeRenderProps(props.className, (className, state) => fieldGroupStyles({ ...state, className })) }));
34
+ }
35
+ const fieldButton = tv({
36
+ extend: focusRing,
37
+ base: "inline-flex shrink-0 items-center justify-center rounded-mark p-1 text-muted transition-colors duration-(--duration-instant) hover:bg-ink/6 hover:text-ink pressed:bg-ink/10",
38
+ variants: {
39
+ isDisabled: {
40
+ true: "text-line-strong hover:bg-transparent forced-colors:text-[GrayText]",
41
+ },
42
+ },
43
+ });
44
+ /** The button inside a field: the calendar of a date picker, the arrow of a combobox. */
45
+ export function FieldButton(props) {
46
+ return (_jsx(AriaButton, { ...props, className: composeRenderProps(props.className, (className, state) => fieldButton({ ...state, className })) }));
47
+ }
48
+ /**
49
+ * One row of a floating list — the options of a `Select`, the suggestions of a `Suggest`.
50
+ *
51
+ * Context: the same row `ComboBox` draws (control height, the `primary` tint on the row the
52
+ * keyboard is on), so every list that drops from a field reads as one kind of thing whatever
53
+ * control opened it.
54
+ */
55
+ export const listOptionStyles = tv({
56
+ base: "group flex min-h-(--size-control-md) cursor-default items-center gap-2 rounded-control px-2 py-1 text-meta text-ink outline-0 select-none forced-color-adjust-none",
57
+ variants: {
58
+ isFocused: {
59
+ true: "bg-primary/8 forced-colors:bg-[Highlight] forced-colors:text-[HighlightText]",
60
+ },
61
+ isPressed: {
62
+ true: "bg-primary/12",
63
+ },
64
+ isDisabled: {
65
+ true: "text-muted opacity-45 forced-colors:text-[GrayText]",
66
+ },
67
+ },
68
+ });
69
+ /** For a control that only adds to the system's classes. */
70
+ export { composeClasses };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * What a `Field` hands to the control inside it: the id its label points at, the ids that
3
+ * describe it (hint, error), and whether it is in error.
4
+ *
5
+ * Context: `Field` used to hand these through a render prop — `{(aria) => <TextInput
6
+ * id={aria.id} … />}` — on every field of every form. Correct, and three lines of wiring
7
+ * per field that anyone could get wrong (forget `describedBy` and the error is never read
8
+ * aloud). Now a control written directly inside a `Field` reads them from here; the render
9
+ * prop still works, and an explicit prop on the control always wins.
10
+ */
11
+ export type FieldIds = {
12
+ id: string;
13
+ /** The id of the field's label. A native input is named by `<label for>`; a React Aria
14
+ * control — a date picker, a combobox — is a group of elements, and is named by this. */
15
+ labelId: string;
16
+ describedBy: string | undefined;
17
+ invalid: boolean;
18
+ };
19
+ export declare const FieldIdsContext: import("react").Context<FieldIds | null>;
20
+ /** The ids of the enclosing `Field`, resolved against the control's own props. */
21
+ export declare function useFieldIds(own: {
22
+ id?: string;
23
+ describedBy?: string;
24
+ invalid?: boolean;
25
+ }): {
26
+ id: string | undefined;
27
+ labelledBy: string | undefined;
28
+ describedBy: string | undefined;
29
+ invalid: boolean;
30
+ };
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { createContext, useContext } from "react";
3
+ export const FieldIdsContext = createContext(null);
4
+ /** The ids of the enclosing `Field`, resolved against the control's own props. */
5
+ export function useFieldIds(own) {
6
+ const field = useContext(FieldIdsContext);
7
+ return {
8
+ id: own.id ?? field?.id,
9
+ labelledBy: field?.labelId,
10
+ describedBy: own.describedBy ?? field?.describedBy,
11
+ invalid: own.invalid ?? field?.invalid ?? false,
12
+ };
13
+ }
@@ -0,0 +1,16 @@
1
+ import { type ReactNode, type RefObject } from "react";
2
+ /** Turns the fields' copy buttons on or off for everything inside. On by default. */
3
+ export declare function FieldCopyProvider({ value, children, }: {
4
+ value: boolean;
5
+ children: ReactNode;
6
+ }): import("react").JSX.Element;
7
+ export declare function useFieldCopy(): boolean;
8
+ /** The text a value area shows, inputs included, placeholders and named buttons left out. */
9
+ export declare function shownText(root: HTMLElement): string;
10
+ /** The button by a field's label. `scope` is the field's value area. */
11
+ export declare function FieldCopy({ label, scope, value, }: {
12
+ label: string;
13
+ scope: RefObject<HTMLElement | null>;
14
+ /** What to copy instead of what is seen. */
15
+ value?: string;
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { fillCopy, useUiCopy } from "../../foundations/copy.js";
4
+ import { CopyButton } from "../value/Copyable.js";
5
+ import { createContext, useContext } from "react";
6
+ /* ==================================================================== *
7
+ * THE COPY BUTTON OF A FIELD — what is on screen, to the clipboard.
8
+ *
9
+ * Context: half of what a record shows is there to be pasted somewhere else —
10
+ * the customer's name into an email, a NIT into the tax portal, a reference
11
+ * into the bank's site. Selecting it by hand fails on exactly those: a
12
+ * many2one is a link that OPENS when pressed, a date is three segments, a
13
+ * number field holds its value in an input. So every `Field` and `DataField`
14
+ * carries a small copy button next to its label, in read mode and in edit
15
+ * mode alike, revealed by the pointer or the focus (always shown on a touch
16
+ * screen, where there is no hover).
17
+ *
18
+ * ── It copies what is SEEN ──────────────────────────────────────────
19
+ *
20
+ * The field does not know its control's value — the control does — so the
21
+ * button reads the value area at the moment of the press: the text drawn,
22
+ * plus what the inputs hold (the name a picker shows, a formatted amount),
23
+ * skipping placeholders (an empty date's «dd/mm/aaaa»), what is hidden, and
24
+ * the named icon buttons inside (a chip's «remove», a summary's «i»). What
25
+ * the person sees is what they paste.
26
+ *
27
+ * ── On by default, never imposed ────────────────────────────────────
28
+ *
29
+ * This system gives possibilities; it does not enclose. `copy="…"` copies
30
+ * something else (the NIT alone, an id the screen does not draw), `copy={false}`
31
+ * removes the button from one field, and `FieldCopyProvider value={false}`
32
+ * from a whole form — a login, a wizard where copying means nothing.
33
+ * ==================================================================== */
34
+ const FieldCopyContext = createContext(true);
35
+ /** Turns the fields' copy buttons on or off for everything inside. On by default. */
36
+ export function FieldCopyProvider({ value, children, }) {
37
+ return _jsx(FieldCopyContext.Provider, { value: value, children: children });
38
+ }
39
+ export function useFieldCopy() {
40
+ return useContext(FieldCopyContext);
41
+ }
42
+ /** What skipping means: not seen, or not the value. */
43
+ const SKIP = '[hidden], [aria-hidden="true"], [data-placeholder], .sr-only, button[aria-label], [data-copy-skip], select';
44
+ /** The text a value area shows, inputs included, placeholders and named buttons left out. */
45
+ export function shownText(root) {
46
+ const parts = [];
47
+ const walk = (node) => {
48
+ if (node.nodeType === Node.TEXT_NODE) {
49
+ parts.push(node.textContent ?? "");
50
+ return;
51
+ }
52
+ if (!(node instanceof HTMLElement) || node.matches(SKIP))
53
+ return;
54
+ if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement) {
55
+ if (node.type !== "hidden")
56
+ parts.push(` ${node.value} `);
57
+ return;
58
+ }
59
+ for (const child of node.childNodes)
60
+ walk(child);
61
+ };
62
+ walk(root);
63
+ return parts.join("").replace(/\s+/g, " ").trim();
64
+ }
65
+ /** The button by a field's label. `scope` is the field's value area. */
66
+ export function FieldCopy({ label, scope, value, }) {
67
+ const ui = useUiCopy();
68
+ return (_jsx("span", { "data-copy-skip": "", className: "inline-flex shrink-0 opacity-0 transition-opacity duration-(--duration-instant) group-hover/field:opacity-100 focus-within:opacity-100 pointer-coarse:opacity-100", children: _jsx(CopyButton, { label: fillCopy(ui.copyable.field, { label }), value: () => value ?? (scope.current === null ? "" : shownText(scope.current)) }) }));
69
+ }
@@ -0,0 +1,9 @@
1
+ export { Checkbox, type CheckItem, CheckList } from "./Checks.js";
2
+ export { type FieldIds, useFieldIds } from "./context.js";
3
+ export { FieldCopyProvider, shownText, useFieldCopy, } from "./copy.js";
4
+ export { DropZone, type DropZoneProps } from "./DropZone.js";
5
+ export { controlClasses, DataField, Field, NumberInput, ReadValue, Select, type SelectOption, TextArea, TextInput, } from "./Field.js";
6
+ export { type FieldLayout, FieldLayoutProvider, useSheetLayout, } from "./layout.js";
7
+ export { type FormMode, FormModeProvider, useFormMode, } from "./mode.js";
8
+ export { Suggest, type SuggestProps } from "./Suggest.js";
9
+ export { type FieldNote } from "./note.js";
@@ -0,0 +1,15 @@
1
+ /* THE CONTROLS a form is written with.
2
+ What ARRANGES them —the sheet, the section, the footer— lives in `components/form`: a
3
+ control does not know a form exists, and is used the same way inside a cell, a filter or
4
+ a dialog. */
5
+ export { Checkbox, CheckList } from "./Checks.js";
6
+ export { useFieldIds } from "./context.js";
7
+ /* The copy button every field carries by its label — on by default, off by field or by form. */
8
+ export { FieldCopyProvider, shownText, useFieldCopy, } from "./copy.js";
9
+ export { DropZone } from "./DropZone.js";
10
+ export { controlClasses, DataField, Field, NumberInput, ReadValue, Select, TextArea, TextInput, } from "./Field.js";
11
+ export { FieldLayoutProvider, useSheetLayout, } from "./layout.js";
12
+ export { FormModeProvider, useFormMode, } from "./mode.js";
13
+ export { Suggest } from "./Suggest.js";
14
+ /* A note that belongs to one field: a card in the record's margin, or a flag by its label. */
15
+ export {} from "./note.js";
@@ -0,0 +1,24 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * HOW A FIELD PLACES ITS LABEL. Declared once, inherited by every field.
4
+ *
5
+ * stacked the label above. The grouped look of iOS. The default.
6
+ * horizontal label | value, and every value starts on the same vertical — the Odoo
7
+ * form, where twenty fields read as a column and not as a bounce.
8
+ *
9
+ * Context: it lives in `primitives/field` and not next to `Sheet`, which declares it,
10
+ * because the one that READS it is `Field` — and a primitive cannot import from a
11
+ * component. The container sets it, the field obeys, and the type that joins them is in the
12
+ * level both can see.
13
+ *
14
+ * Being a context and not a prop is what keeps a sheet from ending up half aligned: nobody
15
+ * has to remember to pass it to each field.
16
+ */
17
+ export type FieldLayout = "stacked" | "horizontal";
18
+ /** The name the sheet knows it by. */
19
+ export type SheetLayout = FieldLayout;
20
+ export declare function useSheetLayout(): FieldLayout;
21
+ export declare function FieldLayoutProvider({ value, children, }: {
22
+ value: FieldLayout;
23
+ children: ReactNode;
24
+ }): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext } from "react";
4
+ const LayoutCtx = createContext("stacked");
5
+ export function useSheetLayout() {
6
+ return useContext(LayoutCtx);
7
+ }
8
+ export function FieldLayoutProvider({ value, children, }) {
9
+ return _jsx(LayoutCtx.Provider, { value: value, children: children });
10
+ }
@@ -0,0 +1,9 @@
1
+ import { type ReactNode } from "react";
2
+ export type FormMode = "edit" | "read";
3
+ export declare function FormModeProvider({ value, children, }: {
4
+ value: FormMode;
5
+ children: ReactNode;
6
+ }): import("react").JSX.Element;
7
+ /** The mode of this field. The prop beats the context — a computed field stays
8
+ * in read mode inside a form that is being edited. */
9
+ export declare function useFormMode(explicit?: FormMode): FormMode;
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext } from "react";
4
+ const Ctx = createContext("edit");
5
+ export function FormModeProvider({ value, children, }) {
6
+ return _jsx(Ctx.Provider, { value: value, children: children });
7
+ }
8
+ /** The mode of this field. The prop beats the context — a computed field stays
9
+ * in read mode inside a form that is being edited. */
10
+ export function useFormMode(explicit) {
11
+ const inherited = useContext(Ctx);
12
+ return explicit ?? inherited;
13
+ }
@@ -0,0 +1,55 @@
1
+ import { type FlagTone } from "../notice/Flag.js";
2
+ import { type ReactNode } from "react";
3
+ /** A note anchored to one field: a sentence, what explains it, and what resolves it. */
4
+ export type FieldNote = {
5
+ /** Without it, `info`. The tone has a shape as well as a colour (`Flag`). */
6
+ tone?: FlagTone;
7
+ /** The sentence: «Vence en 3 días». It names the mark and heads the card. */
8
+ label: string;
9
+ /** What explains it: «NC/2026/0012 por Bs. 1.200,00, sin aplicar». */
10
+ detail?: ReactNode;
11
+ /** What resolves it, if there is something to press: a `Button` with `role="ghost"`
12
+ * and `size="sm"` — the record's primary action is not here. */
13
+ action?: ReactNode;
14
+ };
15
+ /** A note as the record lists it: the note, what it belongs to, and where it is. */
16
+ export type NoteEntry = {
17
+ id: string;
18
+ note: FieldNote;
19
+ /** What it belongs to: «Cliente», «Impresora térmica de tickets 80 mm». */
20
+ owner: string;
21
+ /** The field or row it is anchored to — what «take me there» scrolls to. */
22
+ anchor: () => HTMLElement | null;
23
+ };
24
+ /** The notes mounted in a record. It notifies only when a note appears or goes: a note
25
+ * whose words changed is updated in place, so re-rendering a form (new `note` objects on
26
+ * every render) does not make the record render again, and again. */
27
+ export type NoteRegistry = {
28
+ /** Adds the note, or replaces its words without telling anyone. */
29
+ put: (entry: NoteEntry) => void;
30
+ /** The note went away. */
31
+ drop: (id: string) => void;
32
+ subscribe: (listener: () => void) => () => void;
33
+ snapshot: () => readonly NoteEntry[];
34
+ };
35
+ export declare function createNoteRegistry(): NoteRegistry;
36
+ /** The registry of the record around — `Record` provides it. */
37
+ export declare const NoteRegistryContext: import("react").Context<NoteRegistry | null>;
38
+ /** The notes mounted in the record around, in the order they were mounted. */
39
+ export declare function useNoteEntries(): readonly NoteEntry[];
40
+ /** What a note leaves in its field: its sentence, hidden, for the field's
41
+ * `aria-describedby`, and its entry in the record's activity — where it is listed with
42
+ * what it belongs to and taken back to on press. Nothing is drawn: the mark by the label
43
+ * (`NoteFlag`) says WHERE, the activity says WHAT. */
44
+ export declare function NoteCard({ note, id, owner, }: {
45
+ note: FieldNote;
46
+ id: string;
47
+ /** What it belongs to — the field's label. A row's card reads it from its row. */
48
+ owner?: string;
49
+ }): import("react").JSX.Element;
50
+ /** The mark next to the label: WHERE the note is. It opens the note on press. */
51
+ export declare function NoteFlag({ note }: {
52
+ note: FieldNote;
53
+ }): import("react").JSX.Element;
54
+ /** Joins ids for `aria-describedby`, dropping the absent ones. */
55
+ export declare function describedByOf(...ids: readonly (string | undefined | null)[]): string | undefined;
@@ -0,0 +1,117 @@
1
+ "use client";
2
+ import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
+ import { Flag } from "../notice/Flag.js";
4
+ import { createContext, useContext, useLayoutEffect, useRef, useSyncExternalStore, } from "react";
5
+ export function createNoteRegistry() {
6
+ const entries = new Map();
7
+ const listeners = new Set();
8
+ let list = [];
9
+ const changed = () => {
10
+ list = [...entries.values()];
11
+ for (const listener of listeners)
12
+ listener();
13
+ };
14
+ return {
15
+ put: (entry) => {
16
+ const known = entries.get(entry.id);
17
+ if (known === undefined) {
18
+ entries.set(entry.id, entry);
19
+ changed();
20
+ return;
21
+ }
22
+ /* In place: the snapshot keeps its identity, so `useSyncExternalStore` sees no change
23
+ — a new array here re-rendered the record, which re-rendered the field, which put
24
+ again, for ever. */
25
+ Object.assign(known, entry);
26
+ },
27
+ drop: (id) => {
28
+ if (entries.delete(id))
29
+ changed();
30
+ },
31
+ subscribe: (listener) => {
32
+ listeners.add(listener);
33
+ return () => listeners.delete(listener);
34
+ },
35
+ snapshot: () => list,
36
+ };
37
+ }
38
+ /** The registry of the record around — `Record` provides it. */
39
+ export const NoteRegistryContext = createContext(null);
40
+ const NONE = [];
41
+ const noop = () => () => { };
42
+ /** The notes mounted in the record around, in the order they were mounted. */
43
+ export function useNoteEntries() {
44
+ const registry = useContext(NoteRegistryContext);
45
+ const snapshot = registry?.snapshot ?? (() => NONE);
46
+ /* The same snapshot on the server: nothing registers there (no effects run), so it is
47
+ empty unless someone filled the registry by hand. */
48
+ return useSyncExternalStore(registry?.subscribe ?? noop, snapshot, snapshot);
49
+ }
50
+ /** What a card belongs to when nobody said: the row it sits in, by the first words of its
51
+ * first cell — «Impresora térmica de tickets 80 mm» —, or nothing. The card's own words
52
+ * (it sits in that cell) are skipped. */
53
+ function ownerFromRow(card) {
54
+ const cell = card.closest("tr")?.querySelector("td");
55
+ if (cell === null || cell === undefined)
56
+ return "";
57
+ const walk = document.createTreeWalker(cell, NodeFilter.SHOW_TEXT);
58
+ for (let node = walk.nextNode(); node !== null; node = walk.nextNode()) {
59
+ if (node.parentElement?.closest("[data-field-note]") !== null)
60
+ continue;
61
+ const text = node.textContent?.trim() ?? "";
62
+ if (text !== "")
63
+ return text.slice(0, 60);
64
+ }
65
+ return "";
66
+ }
67
+ /** The field or row a card is anchored to: the row, the fact (a `<dd>`'s group), or the
68
+ * field box the card is the last child of. */
69
+ function anchorOf(card) {
70
+ if (card === null)
71
+ return null;
72
+ const row = card.closest("tr");
73
+ if (row !== null)
74
+ return row;
75
+ const parent = card.parentElement;
76
+ return parent?.tagName === "DD" ? parent.parentElement : parent;
77
+ }
78
+ /* ---------------------------------------------------------------- *
79
+ * The two faces
80
+ * ---------------------------------------------------------------- */
81
+ /** What a note leaves in its field: its sentence, hidden, for the field's
82
+ * `aria-describedby`, and its entry in the record's activity — where it is listed with
83
+ * what it belongs to and taken back to on press. Nothing is drawn: the mark by the label
84
+ * (`NoteFlag`) says WHERE, the activity says WHAT. */
85
+ export function NoteCard({ note, id, owner, }) {
86
+ const registry = useContext(NoteRegistryContext);
87
+ const ref = useRef(null);
88
+ /* Before paint, so the record's activity knows on its first frame whether there is
89
+ anything to align — its default view depends on it. On EVERY render: the words are
90
+ kept current, silently (a new `note` object each render must not re-render the
91
+ record); only appearing and going away are news. */
92
+ useLayoutEffect(() => {
93
+ if (registry === null)
94
+ return;
95
+ const card = ref.current;
96
+ registry.put({
97
+ id,
98
+ note,
99
+ owner: owner ?? (card === null ? "" : ownerFromRow(card)),
100
+ anchor: () => anchorOf(ref.current),
101
+ });
102
+ });
103
+ useLayoutEffect(() => {
104
+ if (registry === null)
105
+ return;
106
+ return () => registry.drop(id);
107
+ }, [registry, id]);
108
+ return (_jsx("div", { ref: ref, "data-field-note": "", hidden: true, children: _jsxs("span", { id: id, children: [note.label, note.detail === undefined ? null : _jsxs(_Fragment, { children: [" \u2014 ", note.detail] })] }) }));
109
+ }
110
+ /** The mark next to the label: WHERE the note is. It opens the note on press. */
111
+ export function NoteFlag({ note }) {
112
+ return (_jsx("span", { className: "inline-flex shrink-0", children: _jsx(Flag, { tone: note.tone ?? "info", label: note.label, children: note.detail === undefined && note.action === undefined ? undefined : (_jsxs("span", { className: "flex flex-col gap-2", children: [note.detail === undefined ? null : _jsx("span", { children: note.detail }), note.action === undefined ? null : _jsx("span", { className: "flex", children: note.action })] })) }) }));
113
+ }
114
+ /** Joins ids for `aria-describedby`, dropping the absent ones. */
115
+ export function describedByOf(...ids) {
116
+ return ids.filter((x) => x !== undefined && x !== null).join(" ") || undefined;
117
+ }
@@ -0,0 +1,31 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * A sentence that does not fit on the page, attached to a mark.
4
+ *
5
+ * Context: `title` on a field is a native tooltip and nobody finds it. Odoo
6
+ * puts a `?` next to the label; pressing it is how you read the help without
7
+ * it eating a line. The mark is the affordance; the sentence is the content.
8
+ *
9
+ * ── Why a click and a popover, and not a `Tooltip` ──
10
+ *
11
+ * A `Tooltip` is a LABEL: a few words that show on hover and vanish when the
12
+ * pointer leaves — useless on a tablet, and gone before a sentence is read.
13
+ * This is content, so it opens on press (mouse, touch, Enter or Space) and
14
+ * stays until it is put away: a second press, Escape, or a click outside. It
15
+ * is React Aria's `DialogTrigger` on the system's `Popover` — the same white
16
+ * surface as a calendar or a small filter form — so placement, flipping when
17
+ * there is no room below, focus moving in and back to the `?`, and Escape are
18
+ * React Aria's, not a hand-written listener.
19
+ *
20
+ * The sentence also lives, hidden, next to the mark under `id`: a field points
21
+ * its `aria-describedby` there, and a closed popover is not in the page for a
22
+ * screen reader to read.
23
+ */
24
+ export declare function Hint({ children, label, id, }: {
25
+ children: ReactNode;
26
+ /** Visible mark. The `?` is the default because it is the one that gets
27
+ * recognized as «there is more to read». */
28
+ label?: ReactNode;
29
+ /** For `aria-describedby` on the field the help belongs to. */
30
+ id?: string;
31
+ }): import("react").JSX.Element;
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { tv } from "../../foundations/variants.js";
4
+ import { Popover } from "../overlay/Popover.js";
5
+ import { CircleHelp } from "lucide-react";
6
+ import { useId } from "react";
7
+ import { Button, Dialog, DialogTrigger } from "react-aria-components";
8
+ const mark = tv({
9
+ base: "inline-flex size-4 shrink-0 cursor-help items-center justify-center rounded-pill text-muted outline-0 transition-colors duration-(--duration-instant) hover:bg-ink/8 hover:text-ink aria-expanded:bg-ink/8 aria-expanded:text-ink forced-colors:text-[ButtonText]",
10
+ variants: {
11
+ isFocusVisible: {
12
+ true: "outline-2 outline-offset-1 outline-primary forced-colors:outline-[Highlight]",
13
+ },
14
+ },
15
+ });
16
+ /**
17
+ * A sentence that does not fit on the page, attached to a mark.
18
+ *
19
+ * Context: `title` on a field is a native tooltip and nobody finds it. Odoo
20
+ * puts a `?` next to the label; pressing it is how you read the help without
21
+ * it eating a line. The mark is the affordance; the sentence is the content.
22
+ *
23
+ * ── Why a click and a popover, and not a `Tooltip` ──
24
+ *
25
+ * A `Tooltip` is a LABEL: a few words that show on hover and vanish when the
26
+ * pointer leaves — useless on a tablet, and gone before a sentence is read.
27
+ * This is content, so it opens on press (mouse, touch, Enter or Space) and
28
+ * stays until it is put away: a second press, Escape, or a click outside. It
29
+ * is React Aria's `DialogTrigger` on the system's `Popover` — the same white
30
+ * surface as a calendar or a small filter form — so placement, flipping when
31
+ * there is no room below, focus moving in and back to the `?`, and Escape are
32
+ * React Aria's, not a hand-written listener.
33
+ *
34
+ * The sentence also lives, hidden, next to the mark under `id`: a field points
35
+ * its `aria-describedby` there, and a closed popover is not in the page for a
36
+ * screen reader to read.
37
+ */
38
+ export function Hint({ children, label = "?", id, }) {
39
+ const auto = useId();
40
+ const textId = id ?? auto;
41
+ return (_jsxs("span", { className: "inline-flex shrink-0", children: [_jsxs(DialogTrigger, { children: [_jsx(Button, { "aria-label": typeof children === "string" ? children : undefined, className: (state) => mark(state), children: label === "?" ? (_jsx(CircleHelp, { className: "size-3.5", strokeWidth: 2, "aria-hidden": true })) : (label) }), _jsx(Popover, { placement: "bottom", className: "max-w-64 rounded-box", children: _jsx(Dialog, { "aria-labelledby": textId, className: "px-3 py-2.5 text-micro leading-relaxed text-ink outline-0", children: children }) })] }), _jsx("span", { id: textId, hidden: true, children: children })] }));
42
+ }
@@ -0,0 +1 @@
1
+ export { Hint } from "./Hint.js";
@@ -0,0 +1 @@
1
+ export { Hint } from "./Hint.js";
@@ -0,0 +1,20 @@
1
+ export * from "./block/index.js";
2
+ export * from "./button/index.js";
3
+ export * from "./cell/index.js";
4
+ export * from "./choice/index.js";
5
+ export * from "./date/index.js";
6
+ export * from "./dialog/index.js";
7
+ export * from "./disclosure/index.js";
8
+ export * from "./field/index.js";
9
+ export * from "./hint/index.js";
10
+ export * from "./menu/index.js";
11
+ export * from "./notice/index.js";
12
+ export * from "./overlay/index.js";
13
+ export * from "./picker/index.js";
14
+ export * from "./surface/index.js";
15
+ export * from "./table/index.js";
16
+ export * from "./tabs/index.js";
17
+ export * from "./tag/index.js";
18
+ export * from "./toolbar/index.js";
19
+ export * from "./tree/index.js";
20
+ export * from "./value/index.js";
@@ -0,0 +1,21 @@
1
+ /* PRIMITIVES — a piece that does not know which screen it is on. */
2
+ export * from "./block/index.js";
3
+ export * from "./button/index.js";
4
+ export * from "./cell/index.js";
5
+ export * from "./choice/index.js";
6
+ export * from "./date/index.js";
7
+ export * from "./dialog/index.js";
8
+ export * from "./disclosure/index.js";
9
+ export * from "./field/index.js";
10
+ export * from "./hint/index.js";
11
+ export * from "./menu/index.js";
12
+ export * from "./notice/index.js";
13
+ export * from "./overlay/index.js";
14
+ export * from "./picker/index.js";
15
+ export * from "./surface/index.js";
16
+ export * from "./table/index.js";
17
+ export * from "./tabs/index.js";
18
+ export * from "./tag/index.js";
19
+ export * from "./toolbar/index.js";
20
+ export * from "./tree/index.js";
21
+ export * from "./value/index.js";