@mantis-core/ui 0.5.0 → 0.6.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 (379) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/COMPONENTS.md +71 -73
  3. package/README.md +13 -6
  4. package/catalog.json +3031 -0
  5. package/dist/components/Buttons/Button.d.ts +39 -9
  6. package/dist/components/Buttons/Button.d.ts.map +1 -1
  7. package/dist/components/Buttons/Button.js +21 -13
  8. package/dist/components/Buttons/Button.js.map +1 -1
  9. package/dist/components/Forms/AutoCompleteField.d.ts +60 -0
  10. package/dist/components/Forms/AutoCompleteField.d.ts.map +1 -0
  11. package/dist/components/Forms/AutoCompleteField.js +125 -0
  12. package/dist/components/Forms/AutoCompleteField.js.map +1 -0
  13. package/dist/components/Forms/CKEditorInput.d.ts +5 -2
  14. package/dist/components/Forms/CKEditorInput.d.ts.map +1 -1
  15. package/dist/components/Forms/CKEditorInput.js +5 -2
  16. package/dist/components/Forms/CKEditorInput.js.map +1 -1
  17. package/dist/components/Forms/CheckboxField.d.ts +14 -0
  18. package/dist/components/Forms/CheckboxField.d.ts.map +1 -0
  19. package/dist/components/Forms/CheckboxField.js +26 -0
  20. package/dist/components/Forms/CheckboxField.js.map +1 -0
  21. package/dist/components/Forms/ColorPickerInput.d.ts +27 -8
  22. package/dist/components/Forms/ColorPickerInput.d.ts.map +1 -1
  23. package/dist/components/Forms/ColorPickerInput.js +57 -11
  24. package/dist/components/Forms/ColorPickerInput.js.map +1 -1
  25. package/dist/components/Forms/DateField.d.ts +68 -0
  26. package/dist/components/Forms/DateField.d.ts.map +1 -0
  27. package/dist/components/Forms/DateField.js +108 -0
  28. package/dist/components/Forms/DateField.js.map +1 -0
  29. package/dist/components/Forms/DatePresets.d.ts.map +1 -1
  30. package/dist/components/Forms/DatePresets.js +6 -3
  31. package/dist/components/Forms/DatePresets.js.map +1 -1
  32. package/dist/components/Forms/FieldShell.d.ts +24 -0
  33. package/dist/components/Forms/FieldShell.d.ts.map +1 -0
  34. package/dist/components/Forms/FieldShell.js +39 -0
  35. package/dist/components/Forms/FieldShell.js.map +1 -0
  36. package/dist/components/Forms/FileDropzone.d.ts +4 -2
  37. package/dist/components/Forms/FileDropzone.d.ts.map +1 -1
  38. package/dist/components/Forms/FileDropzone.js.map +1 -1
  39. package/dist/components/Forms/FormActionsBar.js +2 -2
  40. package/dist/components/Forms/FormActionsBar.js.map +1 -1
  41. package/dist/components/Forms/FormWizard.d.ts +1 -1
  42. package/dist/components/Forms/FormWizard.d.ts.map +1 -1
  43. package/dist/components/Forms/FormWizard.js +4 -5
  44. package/dist/components/Forms/FormWizard.js.map +1 -1
  45. package/dist/components/Forms/HiddenField.d.ts +12 -6
  46. package/dist/components/Forms/HiddenField.d.ts.map +1 -1
  47. package/dist/components/Forms/HiddenField.js +14 -5
  48. package/dist/components/Forms/HiddenField.js.map +1 -1
  49. package/dist/components/Forms/MaskField.d.ts +28 -0
  50. package/dist/components/Forms/MaskField.d.ts.map +1 -0
  51. package/dist/components/Forms/MaskField.js +74 -0
  52. package/dist/components/Forms/MaskField.js.map +1 -0
  53. package/dist/components/Forms/NumberField.d.ts +14 -0
  54. package/dist/components/Forms/NumberField.d.ts.map +1 -0
  55. package/dist/components/Forms/NumberField.js +51 -0
  56. package/dist/components/Forms/NumberField.js.map +1 -0
  57. package/dist/components/Forms/OtpInput.d.ts +23 -8
  58. package/dist/components/Forms/OtpInput.d.ts.map +1 -1
  59. package/dist/components/Forms/OtpInput.js +37 -8
  60. package/dist/components/Forms/OtpInput.js.map +1 -1
  61. package/dist/components/Forms/PasswordInput.d.ts +22 -9
  62. package/dist/components/Forms/PasswordInput.d.ts.map +1 -1
  63. package/dist/components/Forms/PasswordInput.js +63 -28
  64. package/dist/components/Forms/PasswordInput.js.map +1 -1
  65. package/dist/components/Forms/PhoneInput.d.ts +16 -8
  66. package/dist/components/Forms/PhoneInput.d.ts.map +1 -1
  67. package/dist/components/Forms/PhoneInput.js +13 -6
  68. package/dist/components/Forms/PhoneInput.js.map +1 -1
  69. package/dist/components/Forms/RadioGroup.d.ts +34 -13
  70. package/dist/components/Forms/RadioGroup.d.ts.map +1 -1
  71. package/dist/components/Forms/RadioGroup.js +49 -6
  72. package/dist/components/Forms/RadioGroup.js.map +1 -1
  73. package/dist/components/Forms/RangeSlider.d.ts +26 -11
  74. package/dist/components/Forms/RangeSlider.d.ts.map +1 -1
  75. package/dist/components/Forms/RangeSlider.js +40 -7
  76. package/dist/components/Forms/RangeSlider.js.map +1 -1
  77. package/dist/components/Forms/RatingInput.d.ts +24 -8
  78. package/dist/components/Forms/RatingInput.d.ts.map +1 -1
  79. package/dist/components/Forms/RatingInput.js +41 -9
  80. package/dist/components/Forms/RatingInput.js.map +1 -1
  81. package/dist/components/Forms/SearchInput.d.ts +18 -10
  82. package/dist/components/Forms/SearchInput.d.ts.map +1 -1
  83. package/dist/components/Forms/SearchInput.js +44 -23
  84. package/dist/components/Forms/SearchInput.js.map +1 -1
  85. package/dist/components/Forms/SelectField.d.ts +41 -0
  86. package/dist/components/Forms/SelectField.d.ts.map +1 -0
  87. package/dist/components/Forms/SelectField.js +110 -0
  88. package/dist/components/Forms/SelectField.js.map +1 -0
  89. package/dist/components/Forms/SwitchField.d.ts +14 -0
  90. package/dist/components/Forms/SwitchField.d.ts.map +1 -0
  91. package/dist/components/Forms/SwitchField.js +26 -0
  92. package/dist/components/Forms/SwitchField.js.map +1 -0
  93. package/dist/components/Forms/TagsInput.d.ts +29 -8
  94. package/dist/components/Forms/TagsInput.d.ts.map +1 -1
  95. package/dist/components/Forms/TagsInput.js +53 -9
  96. package/dist/components/Forms/TagsInput.js.map +1 -1
  97. package/dist/components/Forms/TextArea.d.ts +13 -10
  98. package/dist/components/Forms/TextArea.d.ts.map +1 -1
  99. package/dist/components/Forms/TextArea.js +27 -9
  100. package/dist/components/Forms/TextArea.js.map +1 -1
  101. package/dist/components/Forms/TextField.d.ts +14 -0
  102. package/dist/components/Forms/TextField.d.ts.map +1 -0
  103. package/dist/components/Forms/TextField.js +29 -0
  104. package/dist/components/Forms/TextField.js.map +1 -0
  105. package/dist/components/Forms/ToggleInlineButton.d.ts +33 -12
  106. package/dist/components/Forms/ToggleInlineButton.d.ts.map +1 -1
  107. package/dist/components/Forms/ToggleInlineButton.js +56 -6
  108. package/dist/components/Forms/ToggleInlineButton.js.map +1 -1
  109. package/dist/components/Forms/UploadFilesPreview.js +3 -3
  110. package/dist/components/Forms/UploadFilesPreview.js.map +1 -1
  111. package/dist/components/Forms/field-typing.test-d.d.ts +2 -0
  112. package/dist/components/Forms/field-typing.test-d.d.ts.map +1 -0
  113. package/dist/components/Forms/field-typing.test-d.js +24 -0
  114. package/dist/components/Forms/field-typing.test-d.js.map +1 -0
  115. package/dist/components/Forms/useFieldController.d.ts +85 -0
  116. package/dist/components/Forms/useFieldController.d.ts.map +1 -0
  117. package/dist/components/Forms/useFieldController.js +54 -0
  118. package/dist/components/Forms/useFieldController.js.map +1 -0
  119. package/dist/components/Loaders/Loading.d.ts.map +1 -1
  120. package/dist/components/Loaders/Loading.js +3 -2
  121. package/dist/components/Loaders/Loading.js.map +1 -1
  122. package/dist/components/Tables/ActionColumn.d.ts +20 -4
  123. package/dist/components/Tables/ActionColumn.d.ts.map +1 -1
  124. package/dist/components/Tables/ActionColumn.js +24 -5
  125. package/dist/components/Tables/ActionColumn.js.map +1 -1
  126. package/dist/components/Tables/FilterPannel.d.ts +9 -2
  127. package/dist/components/Tables/FilterPannel.d.ts.map +1 -1
  128. package/dist/components/Tables/FilterPannel.js +15 -11
  129. package/dist/components/Tables/FilterPannel.js.map +1 -1
  130. package/dist/components/Tables/IndexColumn.d.ts +12 -3
  131. package/dist/components/Tables/IndexColumn.d.ts.map +1 -1
  132. package/dist/components/Tables/IndexColumn.js +21 -5
  133. package/dist/components/Tables/IndexColumn.js.map +1 -1
  134. package/dist/components/Tables/MantisDataTable.d.ts +45 -0
  135. package/dist/components/Tables/MantisDataTable.d.ts.map +1 -0
  136. package/dist/components/Tables/MantisDataTable.js +63 -0
  137. package/dist/components/Tables/MantisDataTable.js.map +1 -0
  138. package/dist/components/Tables/MenuButton.d.ts +28 -7
  139. package/dist/components/Tables/MenuButton.d.ts.map +1 -1
  140. package/dist/components/Tables/MenuButton.js +20 -10
  141. package/dist/components/Tables/MenuButton.js.map +1 -1
  142. package/dist/components/Tables/PaginatedTable.d.ts +26 -17
  143. package/dist/components/Tables/PaginatedTable.d.ts.map +1 -1
  144. package/dist/components/Tables/PaginatedTable.js +24 -22
  145. package/dist/components/Tables/PaginatedTable.js.map +1 -1
  146. package/dist/components/Tables/cell-presets.d.ts +35 -0
  147. package/dist/components/Tables/cell-presets.d.ts.map +1 -0
  148. package/dist/components/Tables/cell-presets.js +40 -0
  149. package/dist/components/Tables/cell-presets.js.map +1 -0
  150. package/dist/components/Tables/columns.d.ts +40 -0
  151. package/dist/components/Tables/columns.d.ts.map +1 -0
  152. package/dist/components/Tables/columns.js +2 -0
  153. package/dist/components/Tables/columns.js.map +1 -0
  154. package/dist/components/Tables/filters/MultiSelectFilter.d.ts +24 -6
  155. package/dist/components/Tables/filters/MultiSelectFilter.d.ts.map +1 -1
  156. package/dist/components/Tables/filters/MultiSelectFilter.js +19 -6
  157. package/dist/components/Tables/filters/MultiSelectFilter.js.map +1 -1
  158. package/dist/components/auth/ChangePasswordForm.d.ts.map +1 -1
  159. package/dist/components/auth/ChangePasswordForm.js +12 -12
  160. package/dist/components/auth/ChangePasswordForm.js.map +1 -1
  161. package/dist/components/auth/ForgotPasswordForm.d.ts.map +1 -1
  162. package/dist/components/auth/ForgotPasswordForm.js +7 -5
  163. package/dist/components/auth/ForgotPasswordForm.js.map +1 -1
  164. package/dist/components/auth/LoginForm.d.ts +2 -2
  165. package/dist/components/auth/LoginForm.d.ts.map +1 -1
  166. package/dist/components/auth/LoginForm.js +15 -15
  167. package/dist/components/auth/LoginForm.js.map +1 -1
  168. package/dist/components/auth/ResetPasswordForm.d.ts.map +1 -1
  169. package/dist/components/auth/ResetPasswordForm.js +11 -12
  170. package/dist/components/auth/ResetPasswordForm.js.map +1 -1
  171. package/dist/components/auth/UserMenu.d.ts +11 -1
  172. package/dist/components/auth/UserMenu.d.ts.map +1 -1
  173. package/dist/components/auth/UserMenu.js +30 -87
  174. package/dist/components/auth/UserMenu.js.map +1 -1
  175. package/dist/components/data/Timeline.d.ts +2 -2
  176. package/dist/components/data/Timeline.d.ts.map +1 -1
  177. package/dist/components/data/Timeline.js +17 -17
  178. package/dist/components/data/Timeline.js.map +1 -1
  179. package/dist/components/feedback/Avatar.d.ts +4 -2
  180. package/dist/components/feedback/Avatar.d.ts.map +1 -1
  181. package/dist/components/feedback/Avatar.js +4 -4
  182. package/dist/components/feedback/Avatar.js.map +1 -1
  183. package/dist/components/feedback/CardSkeleton.d.ts.map +1 -1
  184. package/dist/components/feedback/CardSkeleton.js +3 -3
  185. package/dist/components/feedback/CardSkeleton.js.map +1 -1
  186. package/dist/components/feedback/TableSkeleton.d.ts.map +1 -1
  187. package/dist/components/feedback/TableSkeleton.js +3 -3
  188. package/dist/components/feedback/TableSkeleton.js.map +1 -1
  189. package/dist/components/feedback/Tag.d.ts +4 -2
  190. package/dist/components/feedback/Tag.d.ts.map +1 -1
  191. package/dist/components/feedback/Tag.js +4 -4
  192. package/dist/components/feedback/Tag.js.map +1 -1
  193. package/dist/components/navigation/CommandPalette.d.ts.map +1 -1
  194. package/dist/components/navigation/CommandPalette.js +5 -2
  195. package/dist/components/navigation/CommandPalette.js.map +1 -1
  196. package/dist/components/navigation/PageTabs.d.ts +10 -8
  197. package/dist/components/navigation/PageTabs.d.ts.map +1 -1
  198. package/dist/components/navigation/PageTabs.js +17 -13
  199. package/dist/components/navigation/PageTabs.js.map +1 -1
  200. package/dist/components/overlays/Drawer.d.ts +16 -3
  201. package/dist/components/overlays/Drawer.d.ts.map +1 -1
  202. package/dist/components/overlays/Drawer.js +9 -5
  203. package/dist/components/overlays/Drawer.js.map +1 -1
  204. package/dist/components/overlays/Modal.d.ts +18 -3
  205. package/dist/components/overlays/Modal.d.ts.map +1 -1
  206. package/dist/components/overlays/Modal.js +13 -5
  207. package/dist/components/overlays/Modal.js.map +1 -1
  208. package/dist/components/pages/app-shell/AppShell.d.ts.map +1 -1
  209. package/dist/components/pages/app-shell/AppShell.js +6 -6
  210. package/dist/components/pages/app-shell/AppShell.js.map +1 -1
  211. package/dist/components/ui/ConfirmDialog.d.ts +1 -2
  212. package/dist/components/ui/ConfirmDialog.d.ts.map +1 -1
  213. package/dist/components/ui/ConfirmDialog.js +10 -4
  214. package/dist/components/ui/ConfirmDialog.js.map +1 -1
  215. package/dist/components/ui/DataState.js +2 -2
  216. package/dist/components/ui/DataState.js.map +1 -1
  217. package/dist/index.d.ts +71 -42
  218. package/dist/index.d.ts.map +1 -1
  219. package/dist/index.js +114 -22
  220. package/dist/index.js.map +1 -1
  221. package/docs/README.md +1 -1
  222. package/docs/components/action-column.md +33 -7
  223. package/docs/components/admin-page-configurator.md +24 -5
  224. package/docs/components/admin-page-header.md +21 -3
  225. package/docs/components/admin-page-layout-shell.md +18 -4
  226. package/docs/components/admin-page-layout.md +34 -5
  227. package/docs/components/app-shell.md +31 -6
  228. package/docs/components/auto-complete-field.md +60 -0
  229. package/docs/components/avatar.md +18 -8
  230. package/docs/components/bar-chart.md +25 -7
  231. package/docs/components/breadcrumbs.md +15 -2
  232. package/docs/components/button.md +34 -15
  233. package/docs/components/card-skeleton.md +9 -3
  234. package/docs/components/change-password-form.md +23 -4
  235. package/docs/components/checkbox-field.md +38 -0
  236. package/docs/components/ckeditor-input.md +40 -8
  237. package/docs/components/color-picker-input.md +19 -8
  238. package/docs/components/command-palette.md +23 -2
  239. package/docs/components/confirm-dialog.md +36 -9
  240. package/docs/components/data-state.md +31 -6
  241. package/docs/components/date-field.md +39 -0
  242. package/docs/components/date-presets.md +19 -5
  243. package/docs/components/description-list.md +20 -2
  244. package/docs/components/dirty-form-guard.md +16 -4
  245. package/docs/components/donut-chart.md +24 -7
  246. package/docs/components/drawer.md +27 -8
  247. package/docs/components/empty-state.md +12 -2
  248. package/docs/components/error-boundary.md +16 -2
  249. package/docs/components/error-message.md +22 -3
  250. package/docs/components/field-shell.md +47 -0
  251. package/docs/components/file-dropzone.md +22 -6
  252. package/docs/components/filter-pannel.md +34 -7
  253. package/docs/components/forgot-password-form.md +23 -5
  254. package/docs/components/form-actions-bar.md +21 -2
  255. package/docs/components/form-field-render.md +36 -8
  256. package/docs/components/form-section.md +13 -1
  257. package/docs/components/form-wizard.md +34 -5
  258. package/docs/components/hidden-field.md +22 -6
  259. package/docs/components/index-column.md +25 -5
  260. package/docs/components/line-chart.md +25 -7
  261. package/docs/components/loading.md +14 -5
  262. package/docs/components/login-form.md +31 -6
  263. package/docs/components/mantis-data-table.md +61 -0
  264. package/docs/components/map-picker-client.md +29 -8
  265. package/docs/components/map-picker-osm.md +27 -9
  266. package/docs/components/map-picker.md +25 -4
  267. package/docs/components/mask-field.md +31 -0
  268. package/docs/components/menu-button.md +22 -7
  269. package/docs/components/modal.md +34 -9
  270. package/docs/components/multi-select-filter.md +25 -7
  271. package/docs/components/number-field.md +40 -0
  272. package/docs/components/otp-input.md +20 -7
  273. package/docs/components/page-tabs.md +23 -4
  274. package/docs/components/page-title.md +6 -1
  275. package/docs/components/paginated-table.md +36 -13
  276. package/docs/components/pagination.md +20 -7
  277. package/docs/components/password-input.md +20 -8
  278. package/docs/components/phone-input.md +17 -7
  279. package/docs/components/radio-group.md +39 -9
  280. package/docs/components/range-slider.md +18 -6
  281. package/docs/components/rating-input.md +19 -8
  282. package/docs/components/render-field.md +31 -3
  283. package/docs/components/reset-password-form.md +24 -4
  284. package/docs/components/rich-text-preview.md +17 -5
  285. package/docs/components/search-input.md +18 -7
  286. package/docs/components/select-field.md +55 -0
  287. package/docs/components/stat-card.md +14 -3
  288. package/docs/components/status-badge.md +17 -7
  289. package/docs/components/switch-field.md +32 -0
  290. package/docs/components/table-filter-field.md +22 -4
  291. package/docs/components/table-skeleton.md +9 -3
  292. package/docs/components/table-toolbar.md +18 -5
  293. package/docs/components/tag.md +16 -7
  294. package/docs/components/tags-input.md +21 -8
  295. package/docs/components/text-area.md +18 -8
  296. package/docs/components/text-field.md +32 -0
  297. package/docs/components/timeline.md +19 -3
  298. package/docs/components/toggle-inline-button.md +42 -10
  299. package/docs/components/upload-files-preview.md +23 -2
  300. package/docs/components/use-field-controller.md +58 -0
  301. package/docs/components/user-menu.md +26 -6
  302. package/docs/contracts/STORYBOOK_IMPLEMENTATION_AND_VOBO.md +92 -0
  303. package/docs/contracts/STORYBOOK_VOBO_LEDGER.md +195 -0
  304. package/docs/contracts/component-doc-schema.md +57 -15
  305. package/docs/contracts/dependency-map.md +50 -52
  306. package/docs/contracts/field-controller.md +138 -0
  307. package/docs/contracts/style-imports.md +1 -20
  308. package/llms.txt +70 -72
  309. package/package.json +39 -10
  310. package/dist/components/Forms/AsyncSelect.d.ts +0 -20
  311. package/dist/components/Forms/AsyncSelect.d.ts.map +0 -1
  312. package/dist/components/Forms/AsyncSelect.js +0 -77
  313. package/dist/components/Forms/AsyncSelect.js.map +0 -1
  314. package/dist/components/Forms/Combobox.d.ts +0 -10
  315. package/dist/components/Forms/Combobox.d.ts.map +0 -1
  316. package/dist/components/Forms/Combobox.js +0 -11
  317. package/dist/components/Forms/Combobox.js.map +0 -1
  318. package/dist/components/Forms/CurrencyInput.d.ts +0 -12
  319. package/dist/components/Forms/CurrencyInput.d.ts.map +0 -1
  320. package/dist/components/Forms/CurrencyInput.js +0 -9
  321. package/dist/components/Forms/CurrencyInput.js.map +0 -1
  322. package/dist/components/Forms/DateInput.d.ts +0 -10
  323. package/dist/components/Forms/DateInput.d.ts.map +0 -1
  324. package/dist/components/Forms/DateInput.js +0 -11
  325. package/dist/components/Forms/DateInput.js.map +0 -1
  326. package/dist/components/Forms/DateRangeInput.d.ts +0 -10
  327. package/dist/components/Forms/DateRangeInput.d.ts.map +0 -1
  328. package/dist/components/Forms/DateRangeInput.js +0 -13
  329. package/dist/components/Forms/DateRangeInput.js.map +0 -1
  330. package/dist/components/Forms/DropDown.d.ts +0 -10
  331. package/dist/components/Forms/DropDown.d.ts.map +0 -1
  332. package/dist/components/Forms/DropDown.js +0 -11
  333. package/dist/components/Forms/DropDown.js.map +0 -1
  334. package/dist/components/Forms/MultiSelect.d.ts +0 -10
  335. package/dist/components/Forms/MultiSelect.d.ts.map +0 -1
  336. package/dist/components/Forms/MultiSelect.js +0 -13
  337. package/dist/components/Forms/MultiSelect.js.map +0 -1
  338. package/dist/components/Forms/NumberInput.d.ts +0 -10
  339. package/dist/components/Forms/NumberInput.d.ts.map +0 -1
  340. package/dist/components/Forms/NumberInput.js +0 -16
  341. package/dist/components/Forms/NumberInput.js.map +0 -1
  342. package/dist/components/Forms/Select.d.ts +0 -15
  343. package/dist/components/Forms/Select.d.ts.map +0 -1
  344. package/dist/components/Forms/Select.js +0 -48
  345. package/dist/components/Forms/Select.js.map +0 -1
  346. package/dist/components/Forms/Switch.d.ts +0 -18
  347. package/dist/components/Forms/Switch.d.ts.map +0 -1
  348. package/dist/components/Forms/Switch.js +0 -30
  349. package/dist/components/Forms/Switch.js.map +0 -1
  350. package/dist/components/Forms/TextInput.d.ts +0 -11
  351. package/dist/components/Forms/TextInput.d.ts.map +0 -1
  352. package/dist/components/Forms/TextInput.js +0 -12
  353. package/dist/components/Forms/TextInput.js.map +0 -1
  354. package/dist/components/Forms/TimePicker.d.ts +0 -13
  355. package/dist/components/Forms/TimePicker.d.ts.map +0 -1
  356. package/dist/components/Forms/TimePicker.js +0 -19
  357. package/dist/components/Forms/TimePicker.js.map +0 -1
  358. package/dist/components/Forms/Toggle.d.ts +0 -14
  359. package/dist/components/Forms/Toggle.d.ts.map +0 -1
  360. package/dist/components/Forms/Toggle.js +0 -10
  361. package/dist/components/Forms/Toggle.js.map +0 -1
  362. package/dist/components/Forms/types.d.ts +0 -9
  363. package/dist/components/Forms/types.d.ts.map +0 -1
  364. package/dist/components/Forms/types.js +0 -2
  365. package/dist/components/Forms/types.js.map +0 -1
  366. package/docs/components/async-select.md +0 -27
  367. package/docs/components/combobox.md +0 -19
  368. package/docs/components/currency-input.md +0 -21
  369. package/docs/components/date-input.md +0 -21
  370. package/docs/components/date-range-input.md +0 -20
  371. package/docs/components/drop-down.md +0 -26
  372. package/docs/components/multi-select.md +0 -22
  373. package/docs/components/number-input.md +0 -21
  374. package/docs/components/select.md +0 -28
  375. package/docs/components/switch.md +0 -24
  376. package/docs/components/text-input.md +0 -24
  377. package/docs/components/time-picker.md +0 -25
  378. package/docs/components/toggle.md +0 -24
  379. package/docs/contracts/controller-props.md +0 -28
@@ -2,20 +2,52 @@
2
2
  name: ToggleInlineButton
3
3
  category: forms
4
4
  import: '@mantis-core/ui/components/Forms/ToggleInlineButton'
5
- whenToUse: Segmented button group (single or multi-select) wired to react-hook-form via a controller prop.
6
- baseLibrary: primereact/selectbutton
7
- formContract: ControllerProps
8
- requiredStyles: [scss/select-button.scss]
9
- relatedComponents: [FormFieldRender]
5
+ whenToUse: Segmented single- or multi-choice control over PR11's ToggleButtonGroup; pass `multiple` for array-value mode.
6
+ baseLibrary: '@primereact/ui/togglebutton'
7
+ formContract: ChoiceFieldControllerProps
8
+ relatedComponents: ['RadioGroup', 'SelectField']
10
9
  relatedNextCore: []
11
10
  props:
12
- - { name: controller, type: ControllerProps, required: true, description: 'react-hook-form controller config' }
13
- - { name: options, type: 'any[]', required: true, description: 'Options array passed to SelectButton' }
14
- - { name: variant, type: ButtonVariant, required: false, default: '''primary''', description: 'Design-system color variant' }
15
- - { name: multiple, type: boolean, required: false, default: 'false', description: 'Allow selecting multiple options' }
11
+ - { name: options, type: 'Record<string, unknown>[]', required: true, description: 'Option rows rendered as segments.' }
12
+ - { name: optionLabel, type: string, required: false, default: '''label''', description: 'Key read for each option''s display label.' }
13
+ - { name: optionValue, type: string, required: false, default: '''value''', description: 'Key read for each option''s bound value.' }
14
+ - { name: multiple, type: boolean, required: false, default: 'false', description: 'Array-value mode; toggles per-segment selection instead of single scalar selection.' }
15
+ - { name: renderOption, type: '(option: Record<string, unknown>, index: number) => ReactNode', required: false, description: 'Escape hatch: full custom per-segment render.' }
16
16
  ---
17
+
17
18
  ## Example
18
19
 
19
20
  ```tsx
20
- {/* TODO: add example */}
21
+ import { ToggleInlineButton } from '@mantis-core/ui/components/Forms/ToggleInlineButton';
22
+ import { useForm } from 'react-hook-form';
23
+
24
+ const VIEWS = [
25
+ { label: 'List', value: 'list' },
26
+ { label: 'Grid', value: 'grid' },
27
+ ];
28
+
29
+ function Example() {
30
+ const { control } = useForm({ defaultValues: { view: 'list' } });
31
+ return (
32
+ <ToggleInlineButton
33
+ name='view'
34
+ control={control}
35
+ label='View'
36
+ options={VIEWS}
37
+ optionLabel='label'
38
+ optionValue='value'
39
+ />
40
+ );
41
+ }
21
42
  ```
43
+
44
+ ## Notes
45
+
46
+ - Value shape: scalar (or `null`) by default; an ARRAY when `multiple` — selecting a segment
47
+ appends its value, deselecting filters it out.
48
+ - `labelMode` defaults to `'beside'` for this wrapper (not the global config default).
49
+ - PR11 `11.0.0-rc.1` gotcha (same as `RadioGroup`): the styled `ToggleButtonGroup` and
50
+ `ToggleButton.Root` are wired through two different React contexts in this rc, so the group's
51
+ `value`/`onValueChange` never reaches its children (verified in-browser). Until fixed upstream,
52
+ this wrapper binds each `ToggleButton.Root` individually via its documented `pressed`/
53
+ `onPressedChange` props; `ToggleButtonGroup` itself is used for layout/styling only.
@@ -2,7 +2,7 @@
2
2
  name: UploadFilesPreview
3
3
  category: forms
4
4
  import: '@mantis-core/ui/components/Forms/UploadFilesPreview'
5
- whenToUse: Drag-and-drop upload zone with live preview grid, drag-to-reorder, and async upload queue; designed for image galleries.
5
+ whenToUse: Drag-and-drop upload zone with live preview grid, drag-to-reorder, and async upload queue; designed for image galleries, not react-hook-form bound.
6
6
  baseLibrary: custom
7
7
  relatedComponents: [FileDropzone]
8
8
  relatedNextCore: []
@@ -17,8 +17,29 @@ props:
17
17
  - { name: disabledMessage, type: string, required: false, description: 'Message shown in the drop zone when disabled' }
18
18
  - { name: copy, type: 'Partial<UploadFilesPreviewCopy>', required: false, description: 'Override any UI text strings' }
19
19
  ---
20
+
20
21
  ## Example
21
22
 
22
23
  ```tsx
23
- {/* TODO: add example */}
24
+ import UploadFilesPreview from '@mantis-core/ui/components/Forms/UploadFilesPreview';
25
+
26
+ function Example() {
27
+ return (
28
+ <UploadFilesPreview
29
+ previews={[{ id: '1', fullUrl: 'https://example.com/photo.jpg' }]}
30
+ onUploadFile={async (file) => ({ id: file.name, fullUrl: URL.createObjectURL(file) })}
31
+ onFileUploaded={() => {}}
32
+ onRemoveFile={() => {}}
33
+ onReorder={() => {}}
34
+ />
35
+ );
36
+ }
24
37
  ```
38
+
39
+ ## Notes
40
+
41
+ - Generic over `TItem extends { id: string; fullUrl: string }` — pass richer item shapes for
42
+ gallery-specific metadata.
43
+ - Uploads run per-file via `Promise.allSettled`; a failed `onUploadFile` marks that item `error` in
44
+ the queue with a discard action, it does not throw or block the rest of the batch.
45
+ - Not react-hook-form bound — the parent owns `previews` state and persistence via the callbacks.
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: useFieldController
3
+ category: forms
4
+ import: '@mantis-core/ui/components/Forms/useFieldController'
5
+ whenToUse: 'Hook every RHF field wrapper calls internally to wire useController + a stable id/aria/disabled/error-message resolution; call it directly only when hand-building a new field wrapper (see field-controller.md).'
6
+ baseLibrary: custom
7
+ formContract: FieldControllerProps
8
+ relatedComponents: ['FieldShell', 'TextField']
9
+ relatedNextCore: []
10
+ props: []
11
+ ---
12
+
13
+ ## Example
14
+
15
+ ```tsx
16
+ import { FieldShell } from '@mantis-core/ui/components/Forms/FieldShell';
17
+ import { useFieldController, type FieldControllerProps } from '@mantis-core/ui/components/Forms/useFieldController';
18
+ import { useForm, type FieldValues, type FieldPath } from 'react-hook-form';
19
+
20
+ function RatingField<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>(
21
+ props: FieldControllerProps<TFieldValues, TName>,
22
+ ) {
23
+ const f = useFieldController<TFieldValues, TName>(props);
24
+ return (
25
+ <FieldShell id={f.id} label={props.label} errorMessage={f.errorMessage}>
26
+ <input
27
+ id={f.id}
28
+ type='number'
29
+ value={(f.field.value as number) ?? 0}
30
+ onChange={(e) => f.field.onChange(Number(e.target.value))}
31
+ onBlur={f.field.onBlur}
32
+ disabled={f.disabled}
33
+ {...f.aria}
34
+ />
35
+ </FieldShell>
36
+ );
37
+ }
38
+
39
+ function Example() {
40
+ const { control } = useForm({ defaultValues: { rating: 0 } });
41
+ return <RatingField name='rating' control={control} label='Rating' />;
42
+ }
43
+ ```
44
+
45
+ ## Notes
46
+
47
+ - Takes `FieldControllerProps` verbatim (no extra params) — see
48
+ [`field-controller.md`](../contracts/field-controller.md) for the full prop list.
49
+ - Returns `{ field, fieldState, formState, id, errorId, helpId, variant, size, fluid, invalid,
50
+ disabled, errorMessage, aria }`. `disabled` is `props.disabled || formState.isSubmitting`;
51
+ `aria` is `{ 'aria-invalid', 'aria-describedby' }` (error id wins over help id) — PR11's own
52
+ `invalid` prop only drives styling, so this hook is the one place aria-invalid gets emitted.
53
+ - Portal-based compounds (e.g. `Select`) have no native blur — call `field.onBlur()` from the
54
+ compound's `onOpenChange` (fired on close) instead of relying on a bare blur event, and spread
55
+ `aria` onto the trigger element rather than a hidden input.
56
+ - `TFieldValues` defaults to `FieldValues` (untyped): if a caller omits both `control` and an
57
+ explicit generic, `name` silently accepts any string — pass `control` (or an explicit generic) to
58
+ keep full path-typing.
@@ -2,18 +2,38 @@
2
2
  name: UserMenu
3
3
  category: auth
4
4
  import: '@mantis-core/ui/components/auth/UserMenu'
5
- whenToUse: Topbar user avatar + dropdown with custom nav items and sign-out; no auth lib coupling.
6
- baseLibrary: custom
5
+ whenToUse: Topbar avatar-triggered dropdown (custom nav items + sign-out); no auth-lib coupling.
6
+ baseLibrary: '@primereact/ui/menu'
7
+ requiredStyles: []
8
+ relatedComponents: [Avatar]
7
9
  relatedNextCore: []
8
10
  props:
9
- - { name: user, type: UserMenuUser, required: true }
10
- - { name: items, type: 'UserMenuItem[]', required: false }
11
- - { name: onSignOut, type: '() => void', required: false }
11
+ - { name: user, type: UserMenuUser, required: true, description: '{ name?, email?, avatarUrl? } — displayName falls back to email.' }
12
+ - { name: items, type: 'UserMenuItem[]', required: false, description: '{ label, icon?, href?, onClick? }; href navigates via next/navigation, otherwise onClick fires.' }
13
+ - { name: onSignOut, type: '() => void', required: false, description: 'When set, appends a separator + sign-out item.' }
12
14
  - { name: signOutLabel, type: string, required: false, default: '"Cerrar sesión"' }
13
15
  - { name: className, type: string, required: false }
14
16
  ---
17
+
15
18
  ## Example
16
19
 
17
20
  ```tsx
18
- <UserMenu user={{ name: session.user.name, email: session.user.email }} onSignOut={() => signOut({ callbackUrl: '/login' })} />
21
+ import UserMenu from '@mantis-core/ui/components/auth/UserMenu';
22
+
23
+ function Example() {
24
+ return (
25
+ <UserMenu
26
+ user={{ name: 'Diego Condo', email: 'diego@example.com' }}
27
+ items={[{ label: 'Perfil', icon: 'pi pi-user', href: '/perfil' }]}
28
+ onSignOut={() => console.log('sign out')}
29
+ />
30
+ );
31
+ }
19
32
  ```
33
+
34
+ ## Notes
35
+
36
+ - Migrated to PR11's compound `Menu`: `Menu.Root` owns open state; `Menu.Trigger` renders `as="button"`
37
+ wrapping the migrated `Avatar`. No manual outside-click listener or inline dropdown (PR10 shape) left.
38
+ - Each entry fires through `onSelect` — `href` items call `router.push` (next/navigation), `onClick`
39
+ items just run their handler. `icon` is a PrimeIcons class string (e.g. `pi pi-cog`), not a component.
@@ -0,0 +1,92 @@
1
+ # Storybook Implementation & VoBo Rules — Mantis Core PR11 Forms stage
2
+
3
+ This is the executable contract for finishing the PrimeReact 11 migration of the **reusable** surface
4
+ (Forms family + `Button` + Toast) using Storybook as the isolated workbench and sign-off (VoBo) surface.
5
+ A subagent implementing a component MUST follow **Rule Set 1**; a reviewer/supervisor signing off MUST
6
+ apply **Rule Set 2**. Non-Forms components and `apps/demo-prime11` are FROZEN this stage (do not touch).
7
+
8
+ Scope this stage: existing Forms wrappers (buckets A/B/C), `Button`, Toast migration, and the
9
+ `useDataTableQuery` hook. **Deferred** (segregated but NOT built now): CheckboxGroup, Knob, Listbox,
10
+ ToggleButtonGroup, ButtonGroup, SpeedDial.
11
+
12
+ ---
13
+
14
+ ## Forms segregation by compatibility (READ FIRST)
15
+
16
+ `ifta`/`float` label modes and icon-fields (`InputGroup` addons) apply **only** to text-box inputs.
17
+ Wrapping a checkbox/rating/otp in `FloatLabel`/`IftaLabel`/`InputGroup` breaks the render. Fields are
18
+ segregated into buckets; the props contract is restricted per bucket so misuse fails at compile time.
19
+
20
+ | Bucket | Components | labelMode | Icon addons | Props contract |
21
+ | --- | --- | --- | --- | --- |
22
+ | **A — text-box** | TextField, TextArea\*, NumberField, PasswordInput, SearchInput, MaskField, PhoneInput, SelectField, AutoCompleteField, DateField, TagsInput | `ifta` \| `float`(in/on/over) \| `beside` \| `none` | **Yes** (`addonBefore`/`addonAfter`) | `FieldControllerProps` (full) |
23
+ | **B1 — toggle inline** | CheckboxField, SwitchField, ToggleInlineButton | `beside` \| `none` (default `beside`) | No | `ChoiceFieldControllerProps` |
24
+ | **B2 — group/range** | RadioGroup, RangeSlider, RatingInput, OtpInput, ColorPickerInput | `top` \| `none` (default `top`) | No | `ChoiceFieldControllerProps` |
25
+ | **C — special** | CKEditorInput, FileDropzone (+UploadFilesPreview) → `top`/`none`; HiddenField → no shell | per row | No | own |
26
+
27
+ \* TextArea: label modes yes; icon addons limited/none (document it). PasswordInput/SearchInput/DateField
28
+ have a built-in icon/trigger — document interaction with `addonAfter`.
29
+
30
+ `ChoiceFieldControllerProps = Omit<FieldControllerProps, "labelMode"|"floatVariant"|"addonBefore"|"addonAfter"|"variant"> & { labelMode?: "beside"|"top"|"none" }`.
31
+
32
+ ---
33
+
34
+ ## Rule Set 1 — Implementation
35
+
36
+ ### 1a. General (every reusable component)
37
+
38
+ 1. **Clean PR11 API.** No legacy PR10 aliases; named imports from PR11 subpaths; use the primitive's compound/headless model.
39
+ 2. **Reusable wrapper contract.** Extend/compose the primitive props; **merge `className`/`style`** (never swallow); spread safe `...rest`; overrideable defaults; **typed variants**; `forwardRef` when focus/overlay/scroll/interop matters.
40
+ 3. **Token styling.** Base tokens / CSS vars only; **no hardcoded colors**; keep the `mantis-core-*` namespace; `cssLayer` order `theme, base, primereact`.
41
+ 4. **Layers.** `app → modules|components|lib`, `components → lib`. Forbidden: `components→modules`, `lib→modules`, `lib→app`.
42
+ 5. **Strict typing.** No `any`; `pnpm -s tsc --noEmit` clean.
43
+ 6. **Story required**, co-located, with the bucket's minimum set. No story ⇒ not done.
44
+ 7. **Fix = root cause.** A defect a story reveals is fixed at the shared point, not patched per caller.
45
+
46
+ ### 1b. Forms-specific (configurable fields + RHF)
47
+
48
+ 8. **Every field routes through the shared contract:** `useFieldController` (RHF binding + aria + id) → `FieldShell` (label/addon/help/error). Do not re-implement binding or label placement in the field.
49
+ 9. **Honor the axis per bucket:** A respects `labelMode`(ifta/float/beside/none), `floatVariant`, `variant`, `size`, `fluid` from `useFieldConfig` with per-prop override; B1/B2 use `ChoiceFieldControllerProps` (label `beside`/`top`/`none`, no float/ifta/addons/variant). Never hardcode an applicable axis.
50
+ 10. **Wire value/onChange/onBlur** correctly to the PR11 primitive; **one** `useController` per component.
51
+ 11. **Type coercion at the controller level** when the primitive emits a different shape than the form (NumberField, DateField, OtpInput…). Document the `field.value` shape.
52
+ 12. **Icon groups only in bucket A** via `addonBefore`/`addonAfter`. Pass the addon **wrapped in `InputGroup.Addon`** (from `@primereact/ui/inputgroup`), e.g. `addonBefore={<InputGroup.Addon>@</InputGroup.Addon>}` — raw content (a bare `<span>`) renders detached/unstyled. `FieldShell` owns `InputGroup.Root`; the consumer never wraps the whole field. B/C expose no addons.
53
+ 13. **Cross-field dependencies** use `useWatch` (never `watch()` in render).
54
+ 14. **`required` marker is presentational**; validation lives in `rules`.
55
+ 15. **Docs.** Update the component doc frontmatter / `catalog.json` (`pnpm gen:catalog`) with the `field.value` shape and supported config axes.
56
+
57
+ ### Parametrization (cross-cutting)
58
+
59
+ Every component must be configurable **globally** (context provider: `MantisThemeProvider` → theme/colors/surfaces/dark + `FieldConfigProvider` → labelMode/floatVariant/variant/size/fluid) **or independently** (per-prop override). `Button` and Toast are parametrized by **theme tokens** (no hardcoded color). Everything is exercised from Storybook: global axes via toolbar `globalTypes`, overrides via per-story args.
60
+
61
+ ### Story taxonomy (CSF3) — per bucket
62
+
63
+ Common to all: `Default`, `Playground` (args via `argTypes`), `Invalid` (with `errorMessage`), `Disabled`,
64
+ `HelpText`, `WithReactHookForm` (form-decorator with `defaultValues` + submit that shows the captured value).
65
+ Dark mode and size/variant are exercised via toolbar toggles, not separate stories.
66
+
67
+ - **A (text-box)** — add: `LabelModes` (matrix ifta / float·in / float·on / float·over / beside / none), `Sizes`, `Variants` (outlined/filled), `Fluid`, `WithAddons`. `Async`/`Empty` where applicable (Select/AutoComplete).
68
+ - **B1 (toggle inline)** — add: `LabelBeside`, `LabelNone`. NO float/ifta `LabelModes`, NO `WithAddons`.
69
+ - **B2 (group/range)** — add: `LabelTop`, `LabelNone`, plus control-specific stories (RadioGroup `Options`/`renderOption`, Rating `stars`, Slider `range`). NO float/ifta, NO addons.
70
+ - **C (special)** — a story fitting the component; no label/addon axes.
71
+ - **Button** — `Variants`, `Sizes`, `Severities`, `Outlined`, `Text`, `Rounded`, `Loading`, `Disabled`.
72
+
73
+ ---
74
+
75
+ ## Rule Set 2 — Review & VoBo
76
+
77
+ A component gets VoBo only when **ALL** hold:
78
+
79
+ 1. **Typing** — `pnpm -s tsc --noEmit` clean; no `any`; generics `<TFieldValues, TName>` correct.
80
+ 2. **Best practices / lint** — `pnpm lint` clean; meets the wrapper contract (merge `className`, `...rest`, `forwardRef`, defaults, typed variants); no hardcoded colors.
81
+ 3. **Scalability** — composes over the primitive (does not duplicate it); honors the config axis; no layer-breaking coupling.
82
+ 4. **Meets Rule Set 1** — item-by-item (incl. 1b for Forms).
83
+ 5. **Risk tests** — Vitest green: RHF (value shape, coercion), state, async, transformation.
84
+ 6. **Visual VoBo (most important)** — in the running Storybook, walk **every** story: it looks right; styles not bugged; **no overflow / no "arrows sticking out"**; alignment/spacing/focus/hover/dark/size correct; overlays/portals positioned; **zero console errors**. Check each `labelMode`/`floatVariant` and the icon groups specifically.
85
+ 7. **Supervisor VoBo** — final human sign-off, recorded per component in the ledger.
86
+
87
+ **Support automation (cheap, advisory):** a11y addon (axe) 0 violations per story; render-smoke with no console
88
+ errors. `@storybook/test-runner` (Playwright) and Chromatic are deferred — add only if manual visual review
89
+ stops scaling.
90
+
91
+ Record sign-off in `STORYBOOK_VOBO_LEDGER.md`. A component is not `done` until its row is complete and the
92
+ supervisor has signed.
@@ -0,0 +1,195 @@
1
+ # Storybook VoBo Ledger — PR11 Forms stage
2
+
3
+ Sign-off tracker. A component is **done** only when every column is ✅ and the supervisor has signed.
4
+ Legend: ✅ pass · ⬜ pending · ❌ failing/blocked · N/A not applicable.
5
+ Columns map to `STORYBOOK_IMPLEMENTATION_AND_VOBO.md` Rule Set 2 (typing / lint / rules = Rule Set 1 / tests / visual / supervisor).
6
+
7
+ ## Batch S — Contract segregation
8
+
9
+ | Item | typing | lint | rules | tests | visual | supervisor |
10
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
11
+ | ChoiceFieldControllerProps | ✅ | ⬜ | ✅ | ✅ | N/A | ⬜ |
12
+ | FieldShell `top` mode (hard-cap = type+default, not runtime) | ✅ | ⬜ | ✅ | ✅ | ⬜ (via B2 stories) | ⬜ |
13
+ | field-typing.test-d (B1/B2 reject float/ifta labelMode) | ✅ | ⬜ | ✅ | ✅ | N/A | ⬜ |
14
+
15
+ ## Bucket A — text-box ✅ supervisor VoBo 2026-07-05
16
+
17
+ Story taxonomy + WithAddons (InputGroup.Addon) done; 4 render defects fixed root-cause vs official PR11 docs
18
+ (NumberField addons `InputNumber.Root as={Fragment}`; PasswordInput expose size/variant; SearchInput `fluid`).
19
+ lint column: repo-wide `react-hooks/refs` debt pre-exists on unchanged lines — no NEW lint introduced (†).
20
+
21
+ | Component | typing | lint | rules | tests | visual | supervisor |
22
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
23
+ | TextField | ✅ | † | ✅ | ✅ | ✅ | ✅ |
24
+ | TextArea | ✅ | † | ✅ | N/A | ✅ | ✅ |
25
+ | NumberField | ✅ | † | ✅ | N/A | ✅ | ✅ |
26
+ | PasswordInput | ✅ | † | ✅ | ✅ | ✅ | ✅ |
27
+ | SearchInput | ✅ | † | ✅ | N/A | ✅ | ✅ |
28
+ | MaskField | ✅ | † | ✅ | ✅ | ✅ | ✅ |
29
+ | PhoneInput | ✅ | † | ✅ | ✅ | ✅ | ✅ |
30
+ | SelectField | ✅ | † | ✅ | N/A | ✅‡ | ✅ |
31
+ | AutoCompleteField | ✅ | † | ✅ | N/A | ✅‡ | ✅ |
32
+ | DateField | ✅ | † | ✅ | ✅ | ✅‡ | ✅ |
33
+ | TagsInput | ✅ | † | ✅ | ✅ | ✅‡ | ✅ |
34
+
35
+ ‡ Visual self-verified via Playwright + preview server (DOM measurement + screenshots) after fixing: placeholder overlap, multiselect filter/checkmark, creatable-in-portal, Today/Clear button bar, themed chips, **TagsInput nested focus ring** (the `.p-inputtags` container owns the field border/focus ring — the entry `InputText` was rendering a SECOND border+focus box-shadow/outline; made it chrome-less via inline `border/background/box-shadow/outline:0`, matching PR11's own `.p-inputtags .p-autocomplete-input` rule), and the **fluid axis** (see below). Awaiting final supervisor sign-off.
36
+
37
+ **FLUID AXIS — root-caused + fixed (verified by DOM width measurement, fluid on↔off via the SB globals channel).**
38
+ Root cause: in PrimeReact 11.0.0-rc.1 the `<Fluid>` **context does NOT propagate** to composed inputs inside `FieldShell`
39
+ (`.p-fluid` wrapper renders full-width but the inner `.p-inputtext` stayed inline-block ~181px — no `p-inputtext-fluid`).
40
+ So NO plain field was actually full-width under `config.fluid`; the earlier overlay `w-full` hacks only masked it on Select/Date/AutoComplete.
41
+ Fix (PR11-idiomatic): every PR11 field primitive reads `props.fluid ?? context.$fluid` and applies its `p-<name>-fluid` width:100% class,
42
+ so `useFieldController` now resolves `fluid = props.fluid ?? config.fluid` and each bucket-A field passes `fluid={f.fluid}` to its primitive.
43
+ Verified widths in the 480px story frame (fluid ON → ~416, OFF → intrinsic): TextField 416↔181, TextArea 416↔166, NumberField 416↔181,
44
+ SelectField 416↔62, AutoCompleteField 416↔181, DateField 416↔205 (root **and** inner input — the input sits in `IconField` where the
45
+ `fluid` prop resolves to ~46px, so it keeps `w-full` to fill the fluid-driven root), MaskField/PhoneInput 416↔181.
46
+ Intentionally **always full-width** (their root is a block-level container that fills the parent regardless of the prop — auto-mode would
47
+ leave a mismatched input, and full is the sensible default): SearchInput (`IconField`), PasswordInput (`IconField` in toggle mode), TagsInput (`InputTags`).
48
+
49
+ † Pre-existing repo lint debt (`react-hooks/refs` flags `{...f.aria}`/`f.disabled` spreads across ALL fields, on lines untouched by this work). Tracked as a separate cleanup, not a blocker for this stage.
50
+ | SelectField | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
51
+ | AutoCompleteField | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
52
+ | DateField | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
53
+ | TagsInput | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ |
54
+
55
+ ## Bucket B1 — toggle inline
56
+
57
+ Stories done (Default/HelpText/Required/Disabled/LabelBeside/LabelNone; Toggle adds Multiple/WithRenderOption).
58
+ Visual self-verified via Playwright DOM+interaction (screenshots were flaky): themed controls, label beside,
59
+ click→checked/on/pressed all render (incl. ToggleButton rc-context workaround). No defects. lint = repo debt (†).
60
+
61
+ | Component | typing | lint | rules | tests | visual | supervisor |
62
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
63
+ | CheckboxField | ✅ | † | ✅ | N/A | ✅‡ | ✅ |
64
+ | SwitchField | ✅ | † | ✅ | N/A | ✅‡ | ✅ |
65
+ | ToggleInlineButton | ✅ | † | ✅ | N/A | ✅‡ | ✅ |
66
+
67
+ ## Bucket B2 — group/range
68
+
69
+ Stories done (Default/HelpText/Required/Disabled/LabelTop/LabelNone + control-specific). Visual self-verified via
70
+ Playwright (label on top, themed controls). Fix: RangeSlider range mode rendered ONE handle → now two indexed
71
+ handles (official Slider Range example). lint = repo debt (†). Awaiting final supervisor sign-off.
72
+
73
+ | Component | typing | lint | rules | tests | visual | supervisor |
74
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
75
+ | RadioGroup | ✅ | † | ✅ | ✅ | ✅‡ | ✅ |
76
+ | RangeSlider | ✅ | † | ✅ | ✅ | ✅‡ (fixed range handles) | ✅ |
77
+ | RatingInput | ✅ | † | ✅ | ✅ | ✅‡ | ✅ |
78
+ | OtpInput | ✅ | † | ✅ | ✅ | ✅‡ | ✅ |
79
+ | ColorPickerInput | ✅ | † | ✅ | N/A | ✅‡ | ✅ |
80
+
81
+ ## Bucket C — special
82
+
83
+ Stories written; typecheck + build green. Playwright pass: CKEditor + HiddenField OK; FileDropzone/UploadFilesPreview
84
+ have an open rendering issue (see notes). Batch-0 baseline improved: wired `@mantis-core/styles` SCSS (via sass) into
85
+ `.storybook/preview.tsx`, and CKEditorInput now self-imports `ckeditor5/ckeditor5.css`.
86
+
87
+ | Component | typing | lint | rules | tests | visual | supervisor |
88
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
89
+ | CKEditorInput | ✅ | † | ✅ | ✅ | ✅‡ (self-imports ckeditor CSS + respects tokens) | ✅ |
90
+ | FileDropzone | ✅ | † | ✅ | N/A | ✅‡ (respects tokens — dashed border/surface/icon) | ✅ |
91
+ | UploadFilesPreview | ✅ | † | ✅ | N/A | ✅‡ (respects tokens — dropzone + cover-badge tiles) | ✅ |
92
+ | HiddenField | ✅ | † | ✅ | N/A | N/A (invisible, wiring verified) | ✅‡ |
93
+
94
+ RESOLVED — theme unification + dark mode for the 3 Mantis-token consumers (CKEditor / FileDropzone / UploadFilesPreview):
95
+ these are the ONLY Forms components that paint from the Mantis `--*` token layer (via `@mantis-core/styles` SCSS); every
96
+ other field renders through PrimeReact primitives (`--p-*`) and already followed the toolbar + dark. Two defects, both fixed:
97
+
98
+ 1. **Tokens were static** — `tokens.template.scss` is a fixed brand palette (green, no working dark: its `.dark` block
99
+ keyed off `.dark` while the app toggles `.p-dark`). So the 3 never followed the toolbar primary/surface/dark. Fix:
100
+ `MantisStorybookProvider` now derives the Mantis tokens (`--background/--foreground/--card/--primary/--accent/--muted/
101
+ --border/--input/--ring`) from the SAME `primary`/`surface`/`dark` globals that drive the PR11 preset, set inline on
102
+ `<html>` per active light/dark. `--accent` tracks the primary hue (one step off) so idle/hover two-tone survives.
103
+
104
+ 2. **SCSS anchored fills to literal `white`** — `color-mix(var(--primary), white 96%)` forced near-white surfaces
105
+ regardless of theme (dark impossible). Fix: `white` → `var(--card)` in `file-dropzone.scss`, `ckeditor.scss`
106
+ (blockquote), and `UploadFilesPreview.tsx` inline styles — zero light change (`--card`=white in light), correct in dark.
107
+ Plus a `--ck-*` chrome bridge in `ckeditor.scss` so the CKEditor toolbar/buttons/dropdowns follow the theme (else dark
108
+ icons on dark surface). Verified via Playwright in light+emerald and dark+{rose,ocean}; `build-storybook` exit 0.
109
+
110
+ ## Form utilities
111
+
112
+ | Component | typing | lint | rules | tests | visual | supervisor |
113
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
114
+ Baseline fix this batch: `next/navigation` `useRouter()` crashed all Button-based components in react-vite Storybook
115
+ ("invariant expected app router to be mounted") → aliased to a no-op stub (`.storybook/next-navigation-mock.ts` +
116
+ `main.ts` resolve.alias). Self-verified via Playwright.
117
+
118
+ | FormActionsBar | ✅ | † | ✅ | N/A | ✅‡ (renders after useRouter stub; primary "Guardar" faintness RESOLVED — was missing token layer, `--primary` now resolves) | ⬜ |
119
+ | FormWizard | ✅ | † | ✅ | N/A | ✅‡ (stepper + fields + submit render) | ⬜ |
120
+ | DirtyFormGuard | ✅ | † | ✅ | ⚠️ needs `useDirtyFormGuard.test.ts` (missing; logic-only) | N/A (invisible) | ⬜ |
121
+ | ErrorMessage | ✅ | † | ✅ | ⚠️ small render test recommended | ✅‡ (shows on Submit) | ⬜ |
122
+ | RenderField / FormFieldRender | ✅ | † | ✅ | N/A | ✅‡ (renders fields from descriptor) | ⬜ |
123
+
124
+ ## Buttons
125
+
126
+ Stories authored (co-located `Button.stories.tsx`, title `Buttons/Button`): Default, Variants (8), Outlined, Text,
127
+ Sizes, Rounded, WithIcon, IconOnly, Loading, Disabled, Block, Playground. Visual self-verified via Playwright (light+emerald,
128
+ dark+ocean).
129
+
130
+ **MIGRATED to PR11's native design system (removed the deprecated PR10 SCSS layer)** — supervisor decisions: use PR11
131
+ severity colors from the preset (delete `buttons.scss`), and drop the unused `accent`/`premium` variants.
132
+ - `packages/mantis-core-styles/scss/buttons.scss` **DELETED** (+ its `@use` in `index.scss`). It was the PR10-style layer:
133
+ per-variant `.p-button-<variant>` mixins coloring buttons from Mantis `--*` tokens, plus dead `.p-button-premium`/`accent`.
134
+ - `Button.tsx`: `ButtonVariant` drops `accent` (8 variants); `variant`→PR11 `severity` only (no more `p-button-<variant>` class).
135
+ ALL button colors now come from the PR11 preset. Consequences (intended): `secondary` is now PR11 neutral (was amber),
136
+ `gray`→`contrast` (near-black light / near-white dark), success/warn/danger/info use the Aura severity palettes. `primary`
137
+ follows the toolbar primary ramp. `accent`/`premium` unused repo-wide, so removing them is caller-safe (verified by grep).
138
+ - `Button.test.tsx` updated: assert only the PR11 severity class (`p-button-warn`/`p-button-danger`), not the removed wrapper class. 5/5 pass.
139
+ - **PrimeIcons font**: Button's `icon` string prop (`pi pi-*`) + loading spinner (`pi pi-spin`) need `primeicons/primeicons.css`,
140
+ imported nowhere → added to `.storybook/preview.tsx` + `primeicons` devDep. (Forms use `@primeicons/react` SVG, so it only surfaced here.)
141
+ The earlier "primary Guardar faint" (FormActionsBar) is RESOLVED — was the missing token layer; `--primary` now resolves.
142
+
143
+ **Global severity colors — now controllable via the PR11 preset (not SCSS).** PR11 severity components read from the
144
+ primitive palettes (`success`→`{green}`, `warn`→`{orange}`, `danger`→`{red}`, `info`→`{sky}`; `secondary`/`contrast`→`{surface}`,
145
+ already toolbar-driven). `buildPreset(preset, primary, surface, severities?)` now takes optional per-severity ramps and injects
146
+ `primitive: { green, orange, red, sky }` — recoloring ALL severity components globally (buttons/tags/badges/messages), not just
147
+ buttons. Wired into `MantisThemeConfig.severities` (real `MantisThemeProvider`) + 4 Storybook toolbar dropdowns (Success/Warn/
148
+ Danger/Info), reusing the `PRIMARY_RAMPS` pool. Default (unset) = Aura defaults, byte-identical (no `primitive` block emitted).
149
+ Verified via Playwright: default success=green#22c55e/danger=red#ef4444/warn=orange#f97316/info=sky#0ea5e9; overriding sevSuccess→rose
150
+ recolors the success button to rose (and any severity component) live. next-core + ui typecheck, theme tests 13/13, build green.
151
+
152
+ | Component | typing | lint | rules | tests | visual | supervisor |
153
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
154
+ | Button | ✅ | † | ✅ | ✅ (Button.test.tsx 5/5) | ✅‡ (8 variants PR11-native severities, light+dark, follow toolbar primary; icons+spinner render) | ⬜ |
155
+
156
+ ## Toast (PR11 migration)
157
+
158
+ Migrated `@mantis-core/next-core/toasts` off `react-hot-toast` to PR11's NATIVE toaster (Zag-based singleton `toast` from
159
+ `@primereact/ui/toaster` + `Toast`/`Toaster` compound). `useMantisToasts` API PRESERVED (add{Success,Error,Info,Warning,Loading}Toast,
160
+ promiseToast, jsxToast, dismiss, remove) — now built on `toast.{success,info,warn,error}`/`.promise`/`.dismiss`. Deleted
161
+ `mantis-toast-theme.ts`(+ test) — styling is now native (severity colors from the preset, follow the toolbar). New `MantisToaster`
162
+ host (promoted from the demo's app-toaster pattern) mounted by `MantisCoreBaseProvider` (replaces the react-hot-toast `<Toaster>`;
163
+ `toasterProps` removed). `react-hot-toast` dep removed; `@primereact/ui` added to next-core peers. API deltas (intended): `opts` type
164
+ is now `MantisToastOptions` (Pick of ToastType) not react-hot-toast's; `addLoadingToast` uses `loading:true` + duration Infinity;
165
+ `remove`≡`dismiss`; `jsxToast` callback no longer gets a live toast handle (use the returned id + `dismiss`). CRUD hooks unaffected
166
+ (they mock `../toasts`; crud-hooks.test 6/6). Story `Feedback/Toast` (mounts MantisToaster + buttons per severity + promise + dismiss-all).
167
+ Visual self-verified via playwright-cli: toasts fire, animate in to opacity 1, render severity-themed (success green "Guardado correctamente",
168
+ etc.), auto-dismiss ~5s, loading persists; Zag collapses the stack by default (front shown, hover-expands) — native PR11 behavior.
169
+ typecheck (next-core + ui), build-storybook exit 0.
170
+
171
+ | Item | typing | lint | rules | tests | visual | supervisor |
172
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
173
+ | useMantisToasts (PR11, API preserved) | ✅ | † | ✅ | ✅ (crud-hooks 6/6, mocked) | ✅‡ (fires + severity-themed + auto-dismiss + loading persists) | ⬜ |
174
+ | MantisToaster host | ✅ | † | ✅ | N/A | ✅‡ (renders toasts top-right, Zag stack) | ⬜ |
175
+
176
+ ## Hook
177
+
178
+ Headless `useDataTableQuery` in `@mantis-core/nuqs` (`src/use-data-table-query.ts`): pagination + sorting + filtering in one
179
+ state object, with OPT-IN URL sync via nuqs. Two backends selected by the (construction-time constant) `urlSync`: `useState`
180
+ (headless, no routing) or nuqs `useQueryStates` (deep-link + back/forward) — identical `DataTableQuery<F>` return in both.
181
+ Filter kinds map to parsers: text→`parseAsString`, enum→`createParseAsEnumArray`, stringArray→`parseAsStringArray`, json→`parseAsSuperJson`.
182
+ `setPageSize`/`setFilter`/`setFilters`/`clearFilter`/`resetFilters` reset page to 0; `toggleSort` cycles asc→desc→cleared; `multiSort`
183
+ keeps an array; `queryParams` is the backend-ready `{page,pageSize,sort,filters}`. Root-cause fix along the way: `parseAsSuperJson`
184
+ had an unannotated `createParser` generic that inferred to `null`, making `.withDefault()` uncallable for every caller → annotated
185
+ `createParser<unknown>`. Story `Hooks/useDataTableQuery` — a rich, themed "Directorio de cuentas" admin demo built from the **Mantis
186
+ Forms wrappers** (TextField/SelectField×2 multiple/TagsInput/RangeSlider/DateField/SwitchField in a RHF form bridged one-way to the
187
+ hook via useWatch→setFilters, with a useRef dedupe so unrelated re-renders don't reset page) + a themed sortable table (Tag status
188
+ badges) + Prev/Next + rows-per-page, wired to **REAL nuqs URL sync** via `NuqsAdapter` (`nuqs/adapters/react`, `keyPrefix:"dt"`) and a
189
+ live "URL / queryParams" panel. Verified via playwright-cli in light+emerald AND dark+ocean: typing search → `?dtq=…` + table narrows;
190
+ paginate → `dtpage` (1-based via parseAsIndex) persists (no bridge-reset); sort → `dtsort={json…}`; switch → `dtactiveOnly={json:true}`
191
+ + page resets; Limpiar → URL clean. All complex state (arrays/dates/ranges/booleans/sort) round-trips through the URL.
192
+
193
+ | Item | typing | lint | rules | tests | visual | supervisor |
194
+ | --- | :--: | :--: | :--: | :--: | :--: | :--: |
195
+ | useDataTableQuery | ✅ | † | ✅ | ✅ (17/17: local + URL round-trip per filter kind) | ✅‡ (live: paginate 01-05→06-10, search resets page, enum filter, reset — all correct) | ⬜ |
@@ -12,25 +12,30 @@ edit them by hand. To document a component, edit its `.md` here and re-run the g
12
12
 
13
13
  ```md
14
14
  ---
15
- name: TextInput
15
+ name: TextField
16
16
  category: forms
17
- import: '@mantis-core/ui/components/Forms/TextInput'
17
+ import: '@mantis-core/ui/components/Forms/TextField'
18
18
  whenToUse: Single-line text field wired to react-hook-form.
19
- baseLibrary: primereact/inputtext
20
- formContract: ControllerProps
19
+ baseLibrary: '@primereact/ui/inputtext'
20
+ formContract: FieldControllerProps
21
21
  requiredStyles: ['scss/inputs.scss']
22
- relatedComponents: ['FormFieldRender', 'TextArea']
22
+ relatedComponents: ['SelectField', 'FieldShell']
23
23
  relatedNextCore: []
24
24
  props:
25
- - { name: controller, type: ControllerProps, required: true }
26
- - { name: block, type: boolean, required: false, default: false }
27
- - { name: defaultValue, type: string, required: false, default: "''" }
25
+ - { name: placeholder, type: string, required: false, description: 'Native <input> passthrough beyond FieldControllerProps.' }
26
+ - { name: maxLength, type: number, required: false, description: 'Native <input> passthrough beyond FieldControllerProps.' }
28
27
  ---
29
28
 
30
29
  ## Example
31
30
 
32
31
  ```tsx
33
- <TextInput controller={{ name: 'title' }} block />
32
+ import { TextField } from '@mantis-core/ui/components/Forms/TextField';
33
+ import { useForm } from 'react-hook-form';
34
+
35
+ function Example() {
36
+ const { control } = useForm({ defaultValues: { title: '' } });
37
+ return <TextField name='title' control={control} label='Title' />;
38
+ }
34
39
  ```
35
40
 
36
41
  ## Notes
@@ -46,21 +51,58 @@ props:
46
51
  | `category` | string | ✅ | One of: `forms`, `tables`, `pages`, `maps`, `overlays`, `navigation`, `data`, `feedback`, `auth`, `buttons`, `charts`. Groups `catalog.json`. |
47
52
  | `import` | string | ✅¹ | **Deep path**, verbatim into `catalog.json.import`. Form `@mantis-core/ui/components/<Area>/<Name>`. Exceptions exist (`.../components/table-toolbar`, `.../components/table-filter-field`) — store the real path, do not derive it. ¹Omit **only** for overview/guide docs (e.g. `admin-page-layout.md`): an `import`-less file ships but is excluded from `catalog.json` and `llms.txt`. |
48
53
  | `whenToUse` | string | ✅ | One line. Drives `catalog.json.whenToUse` + the `llms.txt` index. |
49
- | `baseLibrary` | string | ➖ | Underlying lib (`primereact/inputtext`, `react-select`, `custom`). Drives `dependency-map.md`. Use `custom` for components with no third-party base. |
50
- | `formContract` | string | ➖ | Shared contract the component follows, e.g. `ControllerProps`. Omit if none. |
54
+ | `baseLibrary` | string | ➖ | Underlying lib. One of: `@primereact/ui/<part>` (e.g. `@primereact/ui/select`, `@primereact/ui/inputtext`, `@primereact/ui/datatable`), `chart.js`, `leaflet`, `ckeditor`, or `custom` for components with no third-party base. Drives `dependency-map.md`. |
55
+ | `formContract` | string | ➖ | Shared contract the component follows. RHF-bound field wrappers use `FieldControllerProps` (see [`field-controller.md`](./field-controller.md)); non-text-box fields (toggles, groups, ranges) use `ChoiceFieldControllerProps`. Omit if the component isn't RHF-bound. |
51
56
  | `requiredStyles` | string[] | ➖ | SCSS partials from `@mantis-core/styles`, e.g. `['scss/inputs.scss']`. Drives `style-imports.md`. Empty/omit when the component uses only utility classes or inline styles. |
52
57
  | `relatedComponents` | string[] | ➖ | Sibling component `name`s. Cross-reference for LLMs. |
53
58
  | `relatedNextCore` | string[] | ➖ | Hooks/utils from `@mantis-core/next-core` it pairs with, e.g. `['useList']`. Empty for stateless components. |
54
- | `props` | object[] | ✅ | Each: `{ name, type, required, default?, description? }`. `name`/`type` strings, `required` boolean, `default`/`description` optional strings. Maps 1:1 to `catalog.json.props[]`. Empty array `[]` for components with no documented props (factories, etc.). |
59
+ | `props` | object[] | ✅ | Each: `{ name, type, required, default?, description? }`. `name`/`type` strings, `required` boolean, `default`/`description` optional strings. Maps 1:1 to `catalog.json.props[]`. For a wrapper extending `FieldControllerProps`/`ChoiceFieldControllerProps`, list only the props it adds or overrides beyond the shared contract (link the contract via `formContract` instead of repeating `name`/`control`/`rules`/… on every wrapper). Empty array `[]` for components with no documented props (factories, etc.). |
60
+
61
+ ## `formContract`: the flattened API (PR11)
62
+
63
+ Form wrappers no longer take a `controller={{ ... }}` object prop. They extend
64
+ `FieldControllerProps` (or `ChoiceFieldControllerProps` for non-text-box fields) directly as their
65
+ own props, alongside their component-specific props:
66
+
67
+ ```tsx
68
+ // PR11 — flattened, no `controller` object
69
+ <TextField name='email' control={control} label='Email' rules={{ required: true }} />
70
+
71
+ // NOT this (PR10 shape, removed)
72
+ <TextInput controller={{ name: 'email', control }} label='Email' />
73
+ ```
74
+
75
+ See [`field-controller.md`](./field-controller.md) for the full prop list, `FieldShell` label
76
+ modes, and the recipe for building a new wrapper.
55
77
 
56
78
  ## Body
57
79
 
58
80
  - `## Example` — **enforced**: if the `## Example` heading is present it MUST contain exactly one fenced
59
81
  ```tsx block (closing fence on its own line) — the generator throws otherwise. The code inside is
60
- extracted verbatim into `catalog.json.example`. Keep it copy-pasteable. Use the heading `## Example`
61
- (singular); `## Examples` is not recognized. Avoid an inline ``` inside the snippet.
82
+ extracted verbatim into `catalog.json.example`. Use the heading `## Example` (singular); `##
83
+ Examples` is not recognized. Avoid an inline ``` inside the snippet.
84
+ - **Self-contained and compilable**: the `## Example` snippet MUST include its own `import`
85
+ statements — importing the component from the exact deep path declared in frontmatter `import`,
86
+ plus any other modules it uses (`react-hook-form`, other Mantis Core components, etc.) — and MUST
87
+ define a `function Example() { ... }` component that renders the snippet's JSX. A CI check
88
+ compiles every doc's `## Example` block in isolation (no ambient imports, no shared scope across
89
+ docs), so a snippet missing an import or referencing an undefined variable fails the build. Only
90
+ this `## Example` fence is compiled by `check-doc-examples`; other ```tsx fences elsewhere in a
91
+ doc are illustrative and not type-checked. Keep it copy-pasteable and minimal — one realistic
92
+ usage, not a feature tour.
62
93
  - `## Notes` — optional prose. Not consumed by the generator beyond shipping in the `.md`.
63
94
 
95
+ ## Multi-package docs
96
+
97
+ The same frontmatter-driven approach extends beyond `@mantis-core/ui` to `@mantis-core/next-core`,
98
+ `@mantis-core/nuqs`, and `@mantis-core/styles`. Each package's `docs/*.md` files use the same
99
+ minimal frontmatter subset — `name`, `import`, `whenToUse`, `props` — with `category` taking
100
+ per-package values (e.g. `providers`, `theme`, `toasts` for `next-core`; `hooks`, `parsers` for
101
+ `nuqs`; `styles` for `styles`). A generator produces a per-package `llms.txt` from these files, the
102
+ same way `pnpm gen:catalog` does for `@mantis-core/ui`. This section is a pointer only — the
103
+ frontmatter contract and `## Example` rules above apply as-is; generator specifics live with that
104
+ package's own generator script, not here.
105
+
64
106
  ## Generated outputs (do not hand-edit)
65
107
 
66
108
  | Output | Built from |
@@ -73,6 +115,6 @@ props:
73
115
 
74
116
  ## Hand-maintained (not generated)
75
117
 
76
- - `docs/contracts/controller-props.md` — shared contract, not derivable from one component.
118
+ - `docs/contracts/field-controller.md` — shared RHF contract, not derivable from one component.
77
119
  - `docs/README.md`, `README.md` — narrative docs.
78
120
  - Each component's `## Notes` prose.