@recursica/adapter-mui-v7 1.0.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 (389) hide show
  1. package/.storybook/commonArgTypes.ts +148 -0
  2. package/ARCHITECTURE.md +18 -0
  3. package/CHANGELOG.md +582 -0
  4. package/LICENSE +21 -0
  5. package/OVERSTYLING.md +59 -0
  6. package/README.md +70 -0
  7. package/SETUP.md +92 -0
  8. package/USAGE.md +57 -0
  9. package/dist/adapter-mui-v7.cjs +292 -0
  10. package/dist/adapter-mui-v7.cjs.map +1 -0
  11. package/dist/adapter-mui-v7.css +1 -0
  12. package/dist/adapter-mui-v7.js +40757 -0
  13. package/dist/adapter-mui-v7.js.map +1 -0
  14. package/dist/index.d.ts +2350 -0
  15. package/dist/vite.svg +1 -0
  16. package/docs/PHILOSOPHY.md +39 -0
  17. package/llms.txt +76 -0
  18. package/package.json +151 -0
  19. package/recursica_brand.json +2677 -0
  20. package/recursica_tokens.json +799 -0
  21. package/recursica_ui-kit.json +14981 -0
  22. package/recursica_variables_scoped.css +30489 -0
  23. package/src/GlobalExemptions.modules.css +7 -0
  24. package/src/Introduction.stories.tsx +184 -0
  25. package/src/OverStyling.tsx +87 -0
  26. package/src/Version.tsx +37 -0
  27. package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +107 -0
  28. package/src/components/Accordion/Accordion.module.css +362 -0
  29. package/src/components/Accordion/Accordion.stories.tsx +198 -0
  30. package/src/components/Accordion/Accordion.test.tsx +1 -0
  31. package/src/components/Accordion/Accordion.tsx +285 -0
  32. package/src/components/Accordion/USAGE.md +43 -0
  33. package/src/components/Accordion/index.ts +1 -0
  34. package/src/components/AssistiveElement/ASSISTIVEELEMENT_IMPLEMENTATION_NOTES.md +59 -0
  35. package/src/components/AssistiveElement/AssistiveElement.module.css +121 -0
  36. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +68 -0
  37. package/src/components/AssistiveElement/AssistiveElement.test.tsx +1 -0
  38. package/src/components/AssistiveElement/AssistiveElement.tsx +94 -0
  39. package/src/components/AssistiveElement/USAGE.md +36 -0
  40. package/src/components/AssistiveElement/index.ts +1 -0
  41. package/src/components/AutoComplete/AutoComplete.module.css +456 -0
  42. package/src/components/AutoComplete/AutoComplete.stories.tsx +336 -0
  43. package/src/components/AutoComplete/AutoComplete.test.tsx +1 -0
  44. package/src/components/AutoComplete/AutoComplete.tsx +266 -0
  45. package/src/components/AutoComplete/IMPLEMENTATION_NOTES.md +37 -0
  46. package/src/components/AutoComplete/USAGE.md +68 -0
  47. package/src/components/AutoComplete/index.ts +1 -0
  48. package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +36 -0
  49. package/src/components/Avatar/Avatar.module.css +336 -0
  50. package/src/components/Avatar/Avatar.stories.tsx +92 -0
  51. package/src/components/Avatar/Avatar.test.tsx +1 -0
  52. package/src/components/Avatar/Avatar.tsx +88 -0
  53. package/src/components/Avatar/USAGE.md +38 -0
  54. package/src/components/Avatar/index.ts +1 -0
  55. package/src/components/Badge/Badge.module.css +115 -0
  56. package/src/components/Badge/Badge.stories.tsx +78 -0
  57. package/src/components/Badge/Badge.test.tsx +1 -0
  58. package/src/components/Badge/Badge.tsx +61 -0
  59. package/src/components/Badge/USAGE.md +40 -0
  60. package/src/components/Badge/index.ts +1 -0
  61. package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +51 -0
  62. package/src/components/Breadcrumb/Breadcrumb.module.css +51 -0
  63. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
  64. package/src/components/Breadcrumb/Breadcrumb.test.tsx +1 -0
  65. package/src/components/Breadcrumb/Breadcrumb.tsx +70 -0
  66. package/src/components/Breadcrumb/USAGE.md +42 -0
  67. package/src/components/Breadcrumb/index.ts +1 -0
  68. package/src/components/Button/BUTTON_IMPLEMENTATION_NOTES.md +123 -0
  69. package/src/components/Button/Button.module.css +413 -0
  70. package/src/components/Button/Button.stories.tsx +196 -0
  71. package/src/components/Button/Button.styleIsolation.dom.test.tsx +98 -0
  72. package/src/components/Button/Button.tsx +156 -0
  73. package/src/components/Button/USAGE.md +46 -0
  74. package/src/components/Button/index.ts +1 -0
  75. package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +15 -0
  76. package/src/components/Card/Card.module.css +155 -0
  77. package/src/components/Card/Card.stories.tsx +131 -0
  78. package/src/components/Card/Card.test.tsx +1 -0
  79. package/src/components/Card/Card.tsx +202 -0
  80. package/src/components/Card/USAGE.md +57 -0
  81. package/src/components/Card/index.ts +1 -0
  82. package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +14 -0
  83. package/src/components/Checkbox/Checkbox.module.css +286 -0
  84. package/src/components/Checkbox/Checkbox.stories.tsx +97 -0
  85. package/src/components/Checkbox/Checkbox.test.tsx +1 -0
  86. package/src/components/Checkbox/Checkbox.tsx +259 -0
  87. package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
  88. package/src/components/Checkbox/CheckboxGroup.tsx +148 -0
  89. package/src/components/Checkbox/USAGE.md +36 -0
  90. package/src/components/Checkbox/index.ts +6 -0
  91. package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +102 -0
  92. package/src/components/Chip/Chip.module.css +283 -0
  93. package/src/components/Chip/Chip.stories.tsx +154 -0
  94. package/src/components/Chip/Chip.test.tsx +1 -0
  95. package/src/components/Chip/Chip.tsx +168 -0
  96. package/src/components/Chip/USAGE.md +55 -0
  97. package/src/components/Chip/index.ts +1 -0
  98. package/src/components/Container/Container.stories.tsx +118 -0
  99. package/src/components/Container/Container.test.tsx +1 -0
  100. package/src/components/Container/Container.tsx +51 -0
  101. package/src/components/Container/IMPLEMENTATION_NOTES.md +5 -0
  102. package/src/components/Container/USAGE.md +48 -0
  103. package/src/components/Container/index.ts +1 -0
  104. package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +29 -0
  105. package/src/components/DatePicker/DatePicker.icons.tsx +35 -0
  106. package/src/components/DatePicker/DatePicker.module.css +464 -0
  107. package/src/components/DatePicker/DatePicker.stories.tsx +163 -0
  108. package/src/components/DatePicker/DatePicker.test.tsx +1 -0
  109. package/src/components/DatePicker/DatePicker.tsx +229 -0
  110. package/src/components/DatePicker/USAGE.md +49 -0
  111. package/src/components/DatePicker/index.ts +1 -0
  112. package/src/components/Dropdown/BareDropdown.tsx +168 -0
  113. package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +45 -0
  114. package/src/components/Dropdown/Dropdown.icons.tsx +33 -0
  115. package/src/components/Dropdown/Dropdown.module.css +535 -0
  116. package/src/components/Dropdown/Dropdown.stories.tsx +252 -0
  117. package/src/components/Dropdown/Dropdown.test.tsx +1 -0
  118. package/src/components/Dropdown/Dropdown.tsx +319 -0
  119. package/src/components/Dropdown/USAGE.md +68 -0
  120. package/src/components/Dropdown/index.ts +1 -0
  121. package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +153 -0
  122. package/src/components/FileInput/FileInput.module.css +268 -0
  123. package/src/components/FileInput/FileInput.stories.tsx +313 -0
  124. package/src/components/FileInput/FileInput.test.tsx +1 -0
  125. package/src/components/FileInput/FileInput.tsx +415 -0
  126. package/src/components/FileInput/USAGE.md +145 -0
  127. package/src/components/FileInput/index.ts +1 -0
  128. package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +249 -0
  129. package/src/components/FileUpload/FileUpload.module.css +200 -0
  130. package/src/components/FileUpload/FileUpload.stories.tsx +362 -0
  131. package/src/components/FileUpload/FileUpload.test.tsx +1 -0
  132. package/src/components/FileUpload/FileUpload.tsx +352 -0
  133. package/src/components/FileUpload/USAGE.md +199 -0
  134. package/src/components/FileUpload/index.ts +1 -0
  135. package/src/components/Flex/Flex.stories.tsx +128 -0
  136. package/src/components/Flex/Flex.test.tsx +1 -0
  137. package/src/components/Flex/Flex.tsx +89 -0
  138. package/src/components/Flex/USAGE.md +41 -0
  139. package/src/components/Flex/index.ts +1 -0
  140. package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
  141. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +118 -0
  142. package/src/components/FormControlLayout/FormControlLayout.test.tsx +1 -0
  143. package/src/components/FormControlLayout/FormControlLayout.tsx +72 -0
  144. package/src/components/FormControlLayout/USAGE.md +40 -0
  145. package/src/components/FormControlLayout/index.ts +1 -0
  146. package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +35 -0
  147. package/src/components/FormControlWrapper/FormControlWrapper.module.css +87 -0
  148. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +129 -0
  149. package/src/components/FormControlWrapper/FormControlWrapper.test.tsx +1 -0
  150. package/src/components/FormControlWrapper/FormControlWrapper.tsx +149 -0
  151. package/src/components/FormControlWrapper/USAGE.md +40 -0
  152. package/src/components/FormControlWrapper/index.ts +1 -0
  153. package/src/components/Grid/Grid.module.css +72 -0
  154. package/src/components/Grid/Grid.stories.tsx +161 -0
  155. package/src/components/Grid/Grid.test.tsx +1 -0
  156. package/src/components/Grid/Grid.tsx +155 -0
  157. package/src/components/Grid/IMPLEMENTATION_NOTES.md +24 -0
  158. package/src/components/Grid/USAGE.md +53 -0
  159. package/src/components/Grid/index.ts +1 -0
  160. package/src/components/Group/Group.stories.tsx +120 -0
  161. package/src/components/Group/Group.test.tsx +1 -0
  162. package/src/components/Group/Group.tsx +116 -0
  163. package/src/components/Group/USAGE.md +41 -0
  164. package/src/components/Group/index.ts +1 -0
  165. package/src/components/Heading/Heading.stories.tsx +50 -0
  166. package/src/components/Heading/Heading.test.tsx +1 -0
  167. package/src/components/Heading/Heading.tsx +28 -0
  168. package/src/components/Heading/USAGE.md +36 -0
  169. package/src/components/Heading/index.ts +1 -0
  170. package/src/components/HoverCard/HoverCard.module.css +107 -0
  171. package/src/components/HoverCard/HoverCard.stories.tsx +172 -0
  172. package/src/components/HoverCard/HoverCard.test.tsx +1 -0
  173. package/src/components/HoverCard/HoverCard.tsx +145 -0
  174. package/src/components/HoverCard/USAGE.md +45 -0
  175. package/src/components/HoverCard/index.ts +1 -0
  176. package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +27 -0
  177. package/src/components/Label/Label.module.css +169 -0
  178. package/src/components/Label/Label.stories.tsx +131 -0
  179. package/src/components/Label/Label.test.tsx +1 -0
  180. package/src/components/Label/Label.tsx +96 -0
  181. package/src/components/Label/USAGE.md +36 -0
  182. package/src/components/Label/index.ts +1 -0
  183. package/src/components/Layer/USAGE.md +50 -0
  184. package/src/components/Link/LINK_IMPLEMENTATION_NOTES.md +9 -0
  185. package/src/components/Link/Link.module.css +105 -0
  186. package/src/components/Link/Link.stories.tsx +58 -0
  187. package/src/components/Link/Link.test.tsx +1 -0
  188. package/src/components/Link/Link.tsx +45 -0
  189. package/src/components/Link/USAGE.md +40 -0
  190. package/src/components/Link/index.ts +1 -0
  191. package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +25 -0
  192. package/src/components/Loader/Loader.animate.dom.test.tsx +72 -0
  193. package/src/components/Loader/Loader.module.css +175 -0
  194. package/src/components/Loader/Loader.stories.tsx +123 -0
  195. package/src/components/Loader/Loader.test.tsx +1 -0
  196. package/src/components/Loader/Loader.tsx +72 -0
  197. package/src/components/Loader/USAGE.md +42 -0
  198. package/src/components/Loader/index.ts +1 -0
  199. package/src/components/Menu/IMPLEMENTATION_NOTES.md +5 -0
  200. package/src/components/Menu/Menu.module.css +283 -0
  201. package/src/components/Menu/Menu.stories.tsx +405 -0
  202. package/src/components/Menu/Menu.test.tsx +1 -0
  203. package/src/components/Menu/Menu.tsx +103 -0
  204. package/src/components/Menu/USAGE.md +53 -0
  205. package/src/components/Menu/index.ts +1 -0
  206. package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +31 -0
  207. package/src/components/Modal/Modal.module.css +302 -0
  208. package/src/components/Modal/Modal.stories.tsx +105 -0
  209. package/src/components/Modal/Modal.test.tsx +1 -0
  210. package/src/components/Modal/Modal.tsx +231 -0
  211. package/src/components/Modal/USAGE.md +40 -0
  212. package/src/components/Modal/index.ts +1 -0
  213. package/src/components/NumberInput/NUMBER_INPUT_IMPLEMENTATION_NOTES.md +93 -0
  214. package/src/components/NumberInput/NumberInput.module.css +303 -0
  215. package/src/components/NumberInput/NumberInput.stories.tsx +96 -0
  216. package/src/components/NumberInput/NumberInput.test.tsx +1 -0
  217. package/src/components/NumberInput/NumberInput.tsx +273 -0
  218. package/src/components/NumberInput/USAGE.md +36 -0
  219. package/src/components/NumberInput/index.ts +1 -0
  220. package/src/components/Pagination/IMPLEMENTATION_NOTES.md +40 -0
  221. package/src/components/Pagination/Pagination.icons.tsx +66 -0
  222. package/src/components/Pagination/Pagination.module.css +197 -0
  223. package/src/components/Pagination/Pagination.stories.tsx +48 -0
  224. package/src/components/Pagination/Pagination.test.tsx +1 -0
  225. package/src/components/Pagination/Pagination.tsx +123 -0
  226. package/src/components/Pagination/USAGE.md +36 -0
  227. package/src/components/Pagination/index.ts +1 -0
  228. package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +133 -0
  229. package/src/components/Panel/Panel.module.css +231 -0
  230. package/src/components/Panel/Panel.stories.tsx +227 -0
  231. package/src/components/Panel/Panel.test.tsx +1 -0
  232. package/src/components/Panel/Panel.tsx +186 -0
  233. package/src/components/Panel/USAGE.md +46 -0
  234. package/src/components/Panel/index.ts +1 -0
  235. package/src/components/Popover/IMPLEMENTATION_NOTES.md +22 -0
  236. package/src/components/Popover/Popover.module.css +118 -0
  237. package/src/components/Popover/Popover.stories.tsx +133 -0
  238. package/src/components/Popover/Popover.test.tsx +1 -0
  239. package/src/components/Popover/Popover.tsx +267 -0
  240. package/src/components/Popover/USAGE.md +69 -0
  241. package/src/components/Popover/index.ts +1 -0
  242. package/src/components/Radio/RADIO_IMPLEMENTATION_NOTES.md +12 -0
  243. package/src/components/Radio/Radio.module.css +247 -0
  244. package/src/components/Radio/Radio.stories.tsx +93 -0
  245. package/src/components/Radio/Radio.test.tsx +1 -0
  246. package/src/components/Radio/Radio.tsx +223 -0
  247. package/src/components/Radio/RadioGroup.stories.tsx +117 -0
  248. package/src/components/Radio/RadioGroup.tsx +122 -0
  249. package/src/components/Radio/USAGE.md +36 -0
  250. package/src/components/Radio/index.ts +2 -0
  251. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  252. package/src/components/ReadOnlyField/ReadOnlyField.module.css +54 -0
  253. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +163 -0
  254. package/src/components/ReadOnlyField/ReadOnlyField.test.tsx +1 -0
  255. package/src/components/ReadOnlyField/ReadOnlyField.tsx +108 -0
  256. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  257. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  258. package/src/components/ReadOnlyField/USAGE.md +36 -0
  259. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  260. package/src/components/ReadOnlyField/index.ts +2 -0
  261. package/src/components/RecursicaThemeProvider/USAGE.md +60 -0
  262. package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +14 -0
  263. package/src/components/SegmentedControl/SegmentedControl.module.css +201 -0
  264. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +106 -0
  265. package/src/components/SegmentedControl/SegmentedControl.test.tsx +1 -0
  266. package/src/components/SegmentedControl/SegmentedControl.tsx +149 -0
  267. package/src/components/SegmentedControl/USAGE.md +49 -0
  268. package/src/components/SegmentedControl/index.ts +1 -0
  269. package/src/components/Slider/IMPLEMENTATION_NOTES.md +55 -0
  270. package/src/components/Slider/Slider.module.css +635 -0
  271. package/src/components/Slider/Slider.stories.tsx +282 -0
  272. package/src/components/Slider/Slider.test.tsx +1 -0
  273. package/src/components/Slider/Slider.tsx +435 -0
  274. package/src/components/Slider/USAGE.md +56 -0
  275. package/src/components/Slider/index.ts +1 -0
  276. package/src/components/Stack/Stack.stories.tsx +108 -0
  277. package/src/components/Stack/Stack.test.tsx +1 -0
  278. package/src/components/Stack/Stack.tsx +43 -0
  279. package/src/components/Stack/USAGE.md +41 -0
  280. package/src/components/Stack/index.ts +1 -0
  281. package/src/components/Stepper/IMPLEMENTATION_NOTES.md +120 -0
  282. package/src/components/Stepper/Stepper.module.css +474 -0
  283. package/src/components/Stepper/Stepper.stories.tsx +157 -0
  284. package/src/components/Stepper/Stepper.test.tsx +1 -0
  285. package/src/components/Stepper/Stepper.tsx +240 -0
  286. package/src/components/Stepper/USAGE.md +45 -0
  287. package/src/components/Stepper/index.ts +1 -0
  288. package/src/components/Switch/SWITCH_IMPLEMENTATION_NOTES.md +147 -0
  289. package/src/components/Switch/Switch.module.css +346 -0
  290. package/src/components/Switch/Switch.stories.tsx +114 -0
  291. package/src/components/Switch/Switch.test.tsx +1 -0
  292. package/src/components/Switch/Switch.tsx +294 -0
  293. package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
  294. package/src/components/Switch/SwitchGroup.tsx +156 -0
  295. package/src/components/Switch/USAGE.md +36 -0
  296. package/src/components/Switch/index.ts +2 -0
  297. package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +75 -0
  298. package/src/components/Table/Table.module.css +462 -0
  299. package/src/components/Table/Table.stories.tsx +154 -0
  300. package/src/components/Table/Table.test.tsx +1 -0
  301. package/src/components/Table/Table.tsx +250 -0
  302. package/src/components/Table/USAGE.md +90 -0
  303. package/src/components/Table/index.ts +1 -0
  304. package/src/components/Tabs/IMPLEMENTATION_NOTES.md +76 -0
  305. package/src/components/Tabs/Tabs.module.css +801 -0
  306. package/src/components/Tabs/Tabs.stories.tsx +174 -0
  307. package/src/components/Tabs/Tabs.test.tsx +1 -0
  308. package/src/components/Tabs/Tabs.tsx +103 -0
  309. package/src/components/Tabs/USAGE.md +61 -0
  310. package/src/components/Tabs/index.ts +1 -0
  311. package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +10 -0
  312. package/src/components/Text/Text.stories.tsx +75 -0
  313. package/src/components/Text/Text.test.tsx +1 -0
  314. package/src/components/Text/Text.tsx +19 -0
  315. package/src/components/Text/USAGE.md +40 -0
  316. package/src/components/Text/index.ts +1 -0
  317. package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +42 -0
  318. package/src/components/TextArea/TextArea.module.css +203 -0
  319. package/src/components/TextArea/TextArea.stories.tsx +94 -0
  320. package/src/components/TextArea/TextArea.test.tsx +1 -0
  321. package/src/components/TextArea/TextArea.tsx +162 -0
  322. package/src/components/TextArea/USAGE.md +38 -0
  323. package/src/components/TextArea/index.ts +1 -0
  324. package/src/components/TextField/TextField.module.css +271 -0
  325. package/src/components/TextField/TextField.stories.tsx +162 -0
  326. package/src/components/TextField/TextField.test.tsx +1 -0
  327. package/src/components/TextField/TextField.tsx +182 -0
  328. package/src/components/TextField/USAGE.md +38 -0
  329. package/src/components/TextField/index.ts +1 -0
  330. package/src/components/TimePicker/TIMEPICKER_IMPLEMENTATION_NOTES.md +89 -0
  331. package/src/components/TimePicker/TimePicker.module.css +262 -0
  332. package/src/components/TimePicker/TimePicker.stories.tsx +155 -0
  333. package/src/components/TimePicker/TimePicker.test.tsx +1 -0
  334. package/src/components/TimePicker/TimePicker.tsx +277 -0
  335. package/src/components/TimePicker/USAGE.md +61 -0
  336. package/src/components/TimePicker/index.ts +1 -0
  337. package/src/components/Timeline/IMPLEMENTATION_NOTES.md +42 -0
  338. package/src/components/Timeline/Timeline.module.css +363 -0
  339. package/src/components/Timeline/Timeline.stories.tsx +128 -0
  340. package/src/components/Timeline/Timeline.test.tsx +1 -0
  341. package/src/components/Timeline/Timeline.tsx +90 -0
  342. package/src/components/Timeline/TimelineItem.tsx +95 -0
  343. package/src/components/Timeline/USAGE.md +41 -0
  344. package/src/components/Timeline/index.ts +2 -0
  345. package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +37 -0
  346. package/src/components/Toast/Toast.module.css +193 -0
  347. package/src/components/Toast/Toast.stories.tsx +67 -0
  348. package/src/components/Toast/Toast.test.tsx +1 -0
  349. package/src/components/Toast/Toast.tsx +121 -0
  350. package/src/components/Toast/USAGE.md +42 -0
  351. package/src/components/Toast/index.ts +1 -0
  352. package/src/components/Tooltip/Tooltip.module.css +83 -0
  353. package/src/components/Tooltip/Tooltip.stories.tsx +165 -0
  354. package/src/components/Tooltip/Tooltip.test.tsx +1 -0
  355. package/src/components/Tooltip/Tooltip.tsx +78 -0
  356. package/src/components/Tooltip/USAGE.md +40 -0
  357. package/src/components/Tooltip/index.ts +1 -0
  358. package/src/components/TransferList/TRANSFERLIST_IMPLEMENTATION_NOTES.md +140 -0
  359. package/src/components/TransferList/TransferList.module.css +174 -0
  360. package/src/components/TransferList/TransferList.stories.tsx +121 -0
  361. package/src/components/TransferList/TransferList.test.tsx +1 -0
  362. package/src/components/TransferList/TransferList.tsx +419 -0
  363. package/src/components/TransferList/USAGE.md +77 -0
  364. package/src/components/TransferList/index.ts +1 -0
  365. package/src/components/Tree/IMPLEMENTATION_NOTES.md +53 -0
  366. package/src/components/Tree/Tree.module.css +272 -0
  367. package/src/components/Tree/Tree.stories.tsx +104 -0
  368. package/src/components/Tree/Tree.test.tsx +1 -0
  369. package/src/components/Tree/Tree.tsx +298 -0
  370. package/src/components/Tree/USAGE.md +99 -0
  371. package/src/components/Tree/index.ts +1 -0
  372. package/src/components/Typography/TYPOGRAPHY_IMPLEMENTATION_NOTES.md +17 -0
  373. package/src/components/Typography/Typography.module.css +13 -0
  374. package/src/components/Typography/Typography.test.tsx +1 -0
  375. package/src/components/Typography/Typography.tsx +43 -0
  376. package/src/components/Typography/USAGE.md +40 -0
  377. package/src/components/Typography/index.ts +1 -0
  378. package/src/components/index.ts +50 -0
  379. package/src/env.d.ts +7 -0
  380. package/src/index.ts +194 -0
  381. package/src/types/index.ts +9 -0
  382. package/src/types/scss-modules.d.ts +9 -0
  383. package/src/utils/ColorSchemeWrapper.tsx +23 -0
  384. package/src/utils/RequireAccessibleLabel.ts +1 -0
  385. package/src/utils/copyToClipboard.ts +36 -0
  386. package/src/utils/filterStylingProps.test.ts +85 -0
  387. package/src/utils/filterStylingProps.ts +143 -0
  388. package/src/utils/index.ts +1 -0
  389. package/src/utils/renderRichOption.tsx +51 -0
@@ -0,0 +1,336 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { AutoComplete } from "./AutoComplete";
3
+ import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
4
+ import { renderRichOptionContent } from "../../utils/renderRichOption";
5
+ import styles from "./AutoComplete.module.css";
6
+
7
+ const meta: Meta<typeof AutoComplete> = {
8
+ title: "UI-Kit/AutoComplete",
9
+ component: AutoComplete,
10
+ tags: ["autodocs"],
11
+ parameters: {
12
+ docs: {
13
+ description: {
14
+ component: `
15
+ The \`AutoComplete\` primitive provides a text input with a dropdown menu for displaying suggestions as the user types.
16
+
17
+ ### Architectural Decoupling
18
+ Recursica wraps the internal Mantine \`<Autocomplete>\` component inside the \`WithReadOnlyWrapper\`, ensuring it integrates perfectly with the strict design system form architecture.
19
+
20
+ ### Examples
21
+ Always structure horizontal architectures via the generic \`formLayout\` parameter.
22
+ \`\`\`tsx
23
+ <AutoComplete
24
+ label="Country"
25
+ assistiveText="Select your country of residence."
26
+ data={["United States", "Canada", "Mexico", "United Kingdom", "France"]}
27
+ formLayout="stacked"
28
+ />
29
+ \`\`\`
30
+ `,
31
+ },
32
+ },
33
+ },
34
+ argTypes: {
35
+ ...formControlArgTypes,
36
+ disabled: {
37
+ control: "boolean",
38
+ description:
39
+ "Maps the formal disabled variable states structurally to the input core.",
40
+ },
41
+ error: {
42
+ control: "text",
43
+ description:
44
+ "Applies the strict error string boundary rendering invalid structures seamlessly.",
45
+ },
46
+ required: {
47
+ control: "boolean",
48
+ },
49
+ label: {
50
+ control: "text",
51
+ },
52
+ assistiveText: {
53
+ control: "text",
54
+ },
55
+ readOnly: {
56
+ control: "boolean",
57
+ description:
58
+ "Toggles structural read-only data presentation explicitly blocking standard component bindings.",
59
+ },
60
+ wrapItemText: {
61
+ control: "boolean",
62
+ description:
63
+ "Wraps option label/supportingText onto additional lines instead of truncating with an ellipsis.",
64
+ },
65
+ },
66
+ };
67
+
68
+ export default meta;
69
+
70
+ type Story = StoryObj<typeof AutoComplete>;
71
+
72
+ export const Default: Story = {
73
+ args: {
74
+ disabled: false,
75
+ readOnly: false,
76
+ label: "Country Selection",
77
+ placeholder: "Start typing...",
78
+ data: [
79
+ "United States",
80
+ "Canada",
81
+ "Mexico",
82
+ "United Kingdom",
83
+ "France",
84
+ "Germany",
85
+ "Japan",
86
+ "Brazil",
87
+ "India",
88
+ "Australia",
89
+ ],
90
+ assistiveText: "Search from a predefined list of countries.",
91
+ },
92
+ };
93
+
94
+ export const FormsSideBySide: Story = {
95
+ args: {
96
+ label: "Primary Region",
97
+ placeholder: "Select region...",
98
+ data: ["US-East", "US-West", "EU-Central", "AP-South", "SA-East"],
99
+ assistiveText:
100
+ "Select the primary region for the deployment. This violently long string tests native textual wrapping safely mapping alongside inputs.",
101
+ formLayout: "side-by-side",
102
+ },
103
+ };
104
+
105
+ export const WithLeadingIcon: Story = {
106
+ args: {
107
+ label: "Search Projects",
108
+ placeholder: "Project name...",
109
+ data: ["Alpha", "Beta", "Gamma", "Delta", "Epsilon"],
110
+ leftSection: (
111
+ <svg
112
+ width="24"
113
+ height="24"
114
+ viewBox="0 0 24 24"
115
+ fill="none"
116
+ stroke="currentColor"
117
+ strokeWidth="2"
118
+ strokeLinecap="round"
119
+ strokeLinejoin="round"
120
+ >
121
+ <circle cx="11" cy="11" r="8"></circle>
122
+ <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
123
+ </svg>
124
+ ),
125
+ },
126
+ };
127
+
128
+ export const WithTrailingIcon: Story = {
129
+ args: {
130
+ label: "Validation URL",
131
+ placeholder: "https://recursica.dev",
132
+ data: [
133
+ "https://recursica.dev",
134
+ "https://beta.recursica.dev",
135
+ "https://api.recursica.dev",
136
+ ],
137
+ rightSection: (
138
+ <svg
139
+ width="24"
140
+ height="24"
141
+ viewBox="0 0 24 24"
142
+ fill="none"
143
+ stroke="currentColor"
144
+ strokeWidth="2"
145
+ strokeLinecap="round"
146
+ strokeLinejoin="round"
147
+ >
148
+ <polyline points="20 6 9 17 4 12"></polyline>
149
+ </svg>
150
+ ),
151
+ },
152
+ };
153
+
154
+ const UserIcon = (
155
+ <svg
156
+ width="16"
157
+ height="16"
158
+ viewBox="0 0 24 24"
159
+ fill="none"
160
+ stroke="currentColor"
161
+ strokeWidth="2"
162
+ strokeLinecap="round"
163
+ strokeLinejoin="round"
164
+ >
165
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
166
+ <circle cx="12" cy="7" r="4"></circle>
167
+ </svg>
168
+ );
169
+
170
+ export const WithRichOptions: Story = {
171
+ args: {
172
+ label: "Assignee",
173
+ placeholder: "Search team members...",
174
+ data: [
175
+ {
176
+ value: "jdoe",
177
+ label: "Jane Doe",
178
+ leadingIcon: UserIcon,
179
+ supportingText: "jane.doe@example.com",
180
+ },
181
+ {
182
+ value: "asmith",
183
+ label: "Alex Smith",
184
+ leadingIcon: UserIcon,
185
+ supportingText: "alex.smith@example.com",
186
+ },
187
+ { value: "unassigned", label: "Unassigned" },
188
+ ],
189
+ assistiveText:
190
+ "Each option can show a leading icon and supporting text — see MANTINE_ADAPTER_RICH_OPTION_DATA.md.",
191
+ },
192
+ };
193
+
194
+ export const WithRichOptionsWrapped: Story = {
195
+ args: {
196
+ label: "Assignee",
197
+ placeholder: "Search team members...",
198
+ wrapItemText: true,
199
+ data: [
200
+ {
201
+ value: "jdoe",
202
+ label: "Jane Doe, Senior Staff Engineer, Platform Infrastructure",
203
+ leadingIcon: UserIcon,
204
+ supportingText:
205
+ "jane.doe@example.com — Platform Infrastructure team, on-call rotation lead",
206
+ },
207
+ { value: "unassigned", label: "Unassigned" },
208
+ ],
209
+ assistiveText:
210
+ "wrapItemText=true — long label/supportingText wrap instead of truncating.",
211
+ },
212
+ };
213
+
214
+ const optionRowPreviewClassNames = {
215
+ optionContent: styles.optionContent,
216
+ optionIcon: styles.optionIcon,
217
+ optionText: styles.optionText,
218
+ optionTextWrap: styles.optionTextWrap,
219
+ optionSupportingText: styles.optionSupportingText,
220
+ };
221
+
222
+ const OPTION_ROW_PREVIEW_ITEMS = [
223
+ {
224
+ value: "icon-and-supporting",
225
+ label: "Jane Doe",
226
+ leadingIcon: UserIcon,
227
+ supportingText: "jane.doe@example.com",
228
+ },
229
+ {
230
+ value: "no-icon",
231
+ label: "Alex Smith",
232
+ supportingText:
233
+ "No leadingIcon — label/supportingText shift left, no reserved icon space",
234
+ },
235
+ {
236
+ value: "no-supporting-text",
237
+ label: "Taylor Rivera",
238
+ leadingIcon: UserIcon,
239
+ },
240
+ {
241
+ value: "plain",
242
+ label: "Plain option — no leadingIcon, no supportingText",
243
+ },
244
+ {
245
+ value: "long-text",
246
+ label:
247
+ "A very long option label that, with wrapItemText, wraps onto a second line instead of overflowing the fixed-width dropdown — otherwise it truncates with an ellipsis",
248
+ leadingIcon: UserIcon,
249
+ supportingText:
250
+ "A similarly long supporting text string, to confirm the same wrap-or-truncate behavior applies to it too",
251
+ },
252
+ ];
253
+
254
+ // Renders the option row content directly — outside the MUI Popper portal — inside a container
255
+ // sized to Autocomplete's own max-width token. Spacing between rows, icon/supportingText
256
+ // presence-or-absence alignment, and long-text wrapping/truncation are all much easier to inspect
257
+ // this way than by opening the real (portal-rendered) MUI Autocomplete listbox. See
258
+ // MANTINE_ADAPTER_RICH_OPTION_DATA.md.
259
+ const renderOptionRowPreview = (wrapItemText: boolean) => (
260
+ <div
261
+ className={styles.dropdown}
262
+ style={{
263
+ width:
264
+ "var(--recursica_ui-kit_components_autocomplete_variants_layouts_stacked_properties_max-width)",
265
+ }}
266
+ >
267
+ {OPTION_ROW_PREVIEW_ITEMS.map((item) => (
268
+ <div key={item.value} className={styles.option}>
269
+ {renderRichOptionContent(
270
+ item,
271
+ optionRowPreviewClassNames,
272
+ wrapItemText,
273
+ )}
274
+ </div>
275
+ ))}
276
+ </div>
277
+ );
278
+
279
+ // Default: `wrapItemText` is false — label/supportingText truncate to a single line with an
280
+ // ellipsis instead of wrapping.
281
+ export const RichOptionRowPreview: Story = {
282
+ parameters: {
283
+ controls: { disable: true },
284
+ },
285
+ render: () => renderOptionRowPreview(false),
286
+ };
287
+
288
+ // `wrapItemText: true` — label/supportingText wrap onto additional lines instead of truncating.
289
+ export const RichOptionRowPreviewWrapped: Story = {
290
+ parameters: {
291
+ controls: { disable: true },
292
+ },
293
+ render: () => renderOptionRowPreview(true),
294
+ };
295
+
296
+ export const Disabled: Story = {
297
+ args: {
298
+ label: "Disabled Deployment Node",
299
+ placeholder: "Disabled primitive map...",
300
+ data: ["Node 1", "Node 2", "Node 3"],
301
+ disabled: true,
302
+ },
303
+ };
304
+
305
+ export const ErrorState: Story = {
306
+ args: {
307
+ label: "Cluster Failure",
308
+ placeholder: "Failing component instance...",
309
+ data: ["Cluster A", "Cluster B", "Cluster C"],
310
+ defaultValue: "Invalid Cluster",
311
+ error:
312
+ "Critical runtime node disconnect detected traversing DOM architecture.",
313
+ required: true,
314
+ },
315
+ };
316
+
317
+ export const StaticReadOnly: Story = {
318
+ args: {
319
+ label: "Static ReadOnly Review",
320
+ placeholder: "Ignored...",
321
+ data: ["Option 1", "Option 2"],
322
+ value: "Explicitly Uneditable Bound Output",
323
+ readOnly: true,
324
+ },
325
+ };
326
+
327
+ export const EditableReadOnly: Story = {
328
+ args: {
329
+ label: "Editable ReadOnly Review",
330
+ placeholder: "Ignored until active...",
331
+ data: ["Option 1", "Option 2"],
332
+ defaultValue: "Waiting for Edit Execution",
333
+ readOnly: true,
334
+ labelWithEditIcon: true,
335
+ },
336
+ };
@@ -0,0 +1 @@
1
+ // Placeholder for future Autocomplete component tests. Add tests here if/when needed.
@@ -0,0 +1,266 @@
1
+ import React, { forwardRef } from "react";
2
+ import {
3
+ Autocomplete as MuiAutocomplete,
4
+ type AutocompleteProps as MuiAutocompleteProps,
5
+ TextField as MuiTextField,
6
+ // removed InputWrapperProps
7
+ } from "@mui/material";
8
+ import {
9
+ type ReadOnlyControlProps,
10
+ type RecursicaComboboxItemWithLabel,
11
+ normalizeComboboxData,
12
+ } from "@recursica/adapter-common";
13
+ import {
14
+ filterStylingProps,
15
+ omitUnsupportedProps,
16
+ mergeClassNames,
17
+ type RecursicaOverStyled,
18
+ } from "../../utils/filterStylingProps";
19
+ import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
20
+ import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
21
+ import { renderRichOptionContent } from "../../utils/renderRichOption";
22
+ import styles from "./AutoComplete.module.css";
23
+
24
+ import { type RecursicaAutocompleteProps as BaseRecursicaAutocompleteProps } from "@recursica/adapter-common";
25
+
26
+ export interface RecursicaAutocompleteProps
27
+ extends Omit<
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ MuiAutocompleteProps<any, any, any, any, "div">,
30
+ | "variant"
31
+ | "size"
32
+ | "wrapperProps"
33
+ | "radius"
34
+ | "renderInput"
35
+ | "classes"
36
+ | "defaultValue"
37
+ >,
38
+ Omit<
39
+ RecursicaFormControlWrapperProps,
40
+ | "controlMaxWidth"
41
+ | "controlMinWidth"
42
+ | "error"
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ | keyof MuiAutocompleteProps<any, any, any, any, "div">
45
+ >,
46
+ ReadOnlyControlProps,
47
+ BaseRecursicaAutocompleteProps {}
48
+
49
+ export type AutoCompleteProps = RecursicaOverStyled<RecursicaAutocompleteProps>;
50
+
51
+ export const AutoComplete = forwardRef<HTMLInputElement, AutoCompleteProps>(
52
+ function AutoComplete(props, ref) {
53
+ const {
54
+ overStyled = false,
55
+ formLayout = "stacked",
56
+
57
+ // Label & Wrapper Maps
58
+ labelSize,
59
+ labelAlignment,
60
+ labelOptionalText,
61
+ labelWithEditIcon,
62
+ onLabelEditClick,
63
+
64
+ label,
65
+ assistiveText,
66
+ assistiveWithIcon,
67
+ error,
68
+ required,
69
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
70
+ withAsterisk,
71
+ id,
72
+ className,
73
+ style,
74
+ disabled,
75
+ readOnly,
76
+ readOnlyComponent,
77
+ emptyValueComponent,
78
+ value,
79
+ defaultValue,
80
+ data,
81
+ leftSection,
82
+ rightSection,
83
+ placeholder,
84
+ ListboxProps,
85
+ renderOption,
86
+ wrapItemText = false,
87
+ ...rest
88
+ } = props;
89
+ // Props this component intentionally doesn't support — deleted at runtime so they can't leak
90
+ // through even if a caller forces them via plain JavaScript, bypassing the Omit<> above.
91
+ const UNSUPPORTED_PROPS = [
92
+ "size", // Recursica controls sizing via design tokens, not MUI's native small/medium size
93
+ ] as const satisfies readonly (keyof MuiAutocompleteProps<
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ any,
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ any,
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
+ any,
100
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
101
+ any,
102
+ "div"
103
+ >)[];
104
+
105
+ const sanitizedProps = omitUnsupportedProps(
106
+ filterStylingProps(rest, overStyled),
107
+ UNSUPPORTED_PROPS,
108
+ );
109
+ const restRecord = sanitizedProps as Record<string, unknown>;
110
+
111
+ // Securely map core native blocks down ensuring nested CSS modules map precisely. Note MUI's
112
+ // actual prop is "classes", not "classNames" (that's Mantine's naming) — this used to read
113
+ // the wrong key, silently no-op-ing any caller-supplied classes. The caller-facing slot names
114
+ // below (wrapper/input/dropdown/option) mirror the mantine-adapter's own Autocomplete
115
+ // classNames slots, translated to MUI's real classes slot names (root/inputRoot/listbox/option).
116
+ const callerClasses = restRecord.classes as
117
+ | Partial<Record<string, string>>
118
+ | undefined;
119
+ const mergedClassNames = mergeClassNames(
120
+ {
121
+ root: styles.root,
122
+ inputRoot: styles.input, // Map Mantine .input (wrapper) to MUI's inputRoot
123
+ listbox: styles.dropdown, // Map Mantine .dropdown to MUI's listbox
124
+ option: styles.option,
125
+ },
126
+ callerClasses && {
127
+ root: callerClasses.wrapper,
128
+ inputRoot: callerClasses.input,
129
+ listbox: callerClasses.dropdown,
130
+ option: callerClasses.option,
131
+ },
132
+ );
133
+
134
+ const wrapperClass = className
135
+ ? `${styles.layoutOverride} ${className}`
136
+ : styles.layoutOverride;
137
+
138
+ const optionClassNames = {
139
+ optionContent: styles.optionContent,
140
+ optionIcon: styles.optionIcon,
141
+ optionText: styles.optionText,
142
+ optionTextWrap: styles.optionTextWrap,
143
+ optionSupportingText: styles.optionSupportingText,
144
+ };
145
+
146
+ // See Dropdown.tsx's identical use of `normalizeComboboxData` (adapter-common) — items always
147
+ // have a real `label` after this, so `defaultRenderOption` below doesn't need its own fallback.
148
+ const normalizedData = normalizeComboboxData(data);
149
+
150
+ // Default per-option rendering — kept as a fallback so a caller-supplied `renderOption` (an
151
+ // escape hatch, see MANTINE_ADAPTER_RICH_OPTION_DATA.md) still wins.
152
+ const defaultRenderOption = (
153
+ liProps: React.HTMLAttributes<HTMLLIElement> & { key?: React.Key },
154
+ option: unknown,
155
+ ) => {
156
+ const { key, ...otherProps } = liProps;
157
+ if (typeof option === "string") {
158
+ return (
159
+ <li key={key} {...otherProps}>
160
+ {option}
161
+ </li>
162
+ );
163
+ }
164
+ return (
165
+ <li key={key} {...otherProps}>
166
+ {renderRichOptionContent(
167
+ option as RecursicaComboboxItemWithLabel,
168
+ optionClassNames,
169
+ wrapItemText,
170
+ )}
171
+ </li>
172
+ );
173
+ };
174
+
175
+ return (
176
+ <WithReadOnlyWrapper
177
+ className={wrapperClass}
178
+ style={style as React.CSSProperties}
179
+ controlMaxWidth="var(--autocomplete-control-max-width)"
180
+ controlMinWidth="var(--autocomplete-control-min-width)"
181
+ overStyled={overStyled as true}
182
+ formLayout={formLayout}
183
+ labelSize={labelSize}
184
+ labelAlignment={labelAlignment}
185
+ labelOptionalText={labelOptionalText}
186
+ labelWithEditIcon={labelWithEditIcon}
187
+ onLabelEditClick={onLabelEditClick}
188
+ label={label}
189
+ assistiveText={assistiveText}
190
+ assistiveWithIcon={assistiveWithIcon}
191
+ error={error}
192
+ required={required}
193
+ id={id}
194
+ disabled={disabled}
195
+ readOnly={readOnly}
196
+ readOnlyComponent={readOnlyComponent}
197
+ emptyValueComponent={emptyValueComponent}
198
+ readOnlyType="text"
199
+ readOnlyValue={value !== undefined ? value : defaultValue}
200
+ readOnlyNativeProps={props}
201
+ activeComponent={
202
+ /* Naked Input execution safely decoupled from Mui's macro Input.Wrapper DOM hooks */
203
+ <MuiAutocomplete
204
+ ref={ref}
205
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
+ {...(sanitizedProps as any)}
207
+ freeSolo
208
+ disableClearable
209
+ classes={mergedClassNames}
210
+ disabled={disabled}
211
+ value={value}
212
+ defaultValue={defaultValue}
213
+ forcePopupIcon={false}
214
+ data-error={error ? "true" : undefined}
215
+ data-disabled={disabled ? "true" : undefined}
216
+ data-with-left-section={leftSection ? "true" : undefined}
217
+ data-with-right-section={rightSection ? "true" : undefined}
218
+ ListboxProps={{
219
+ ...ListboxProps,
220
+ className: mergedClassNames.listbox,
221
+ }}
222
+ slotProps={{
223
+ ...(restRecord.slotProps as Record<string, unknown> | undefined),
224
+ popper: {
225
+ ...((restRecord.slotProps as { popper?: object } | undefined)
226
+ ?.popper ?? {}),
227
+ className: styles.popper,
228
+ },
229
+ }}
230
+ options={normalizedData || []}
231
+ renderOption={renderOption ?? defaultRenderOption}
232
+ renderInput={(params) => {
233
+ const { InputProps, ...restParams } = params;
234
+ return (
235
+ <MuiTextField
236
+ {...restParams}
237
+ placeholder={placeholder}
238
+ variant="standard"
239
+ InputProps={{
240
+ ...InputProps,
241
+ startAdornment: leftSection ? (
242
+ <span className={styles.section} data-position="left">
243
+ {leftSection}
244
+ </span>
245
+ ) : (
246
+ InputProps.startAdornment
247
+ ),
248
+ endAdornment: rightSection ? (
249
+ <span className={styles.section} data-position="right">
250
+ {rightSection}
251
+ </span>
252
+ ) : (
253
+ InputProps.endAdornment
254
+ ),
255
+ }}
256
+ />
257
+ );
258
+ }}
259
+ />
260
+ }
261
+ />
262
+ );
263
+ },
264
+ );
265
+
266
+ AutoComplete.displayName = "AutoComplete";
@@ -0,0 +1,37 @@
1
+ # Autocomplete Implementation Notes
2
+
3
+ ## Rich Option Content (`leadingIcon`/`supportingText`)
4
+
5
+ `data` items accept optional `leadingIcon`/`supportingText` fields, via the shared `RecursicaComboboxItem` type in `@recursica/adapter-common` (see `MANTINE_ADAPTER_RICH_OPTION_DATA.md` at the repo root — proposed against the mantine-adapter, but Forge needs both adapters to accept the same `data` shape, hence the type living in adapter-common rather than being redeclared per adapter). `Autocomplete.tsx` runs `data` through adapter-common's `normalizeComboboxData` first (backfills `label` from `value`, since `label` on the shared type is optional), then installs a default `renderOption` that renders each option's `<li>` via `renderRichOptionContent` (`../../utils/renderRichOption.tsx`, shared with `Dropdown`) — `leadingIcon`+`label`+`supportingText` when either new field is present, or just `label` otherwise. A caller-supplied `renderOption` always wins over the default. The icon is only rendered as a child when `leadingIcon` is set (not a hidden reserved slot), so label/supportingText shift left when there's no icon; the row's `align-items: center` keeps the label vertically centered when there's no `supportingText`.
6
+
7
+ Unlike Dropdown, this doesn't need an explicit `renderValue`-equivalent fix: MUI's `Autocomplete` already separates the closed field's text (driven by `getOptionLabel`, which defaults to `option.label`) from the open dropdown's row rendering (`renderOption`), so enriching `renderOption` alone doesn't touch what the closed field shows.
8
+
9
+ New CSS classes (`.optionContent`/`.optionIcon`/`.optionText`/`.optionSupportingText`) in `Autocomplete.module.css` reuse the menu-item component's icon/supporting-text tokens, matching the mantine-adapter's equivalent addition — no dedicated autocomplete-option tokens exist for either.
10
+
11
+ ## `wrapItemText`
12
+
13
+ `label`/`supportingText` default to single-line truncation with an ellipsis (`.optionText > *` — `overflow: clip; overflow-clip-margin: 0.35em; text-overflow: ellipsis; white-space: nowrap`). Passing `wrapItemText` adds `.optionTextWrap` alongside `.optionText`, re-enabling wrapping (`white-space: normal; overflow-wrap: anywhere`) for both children — later-cascade-wins, equal specificity. `renderRichOptionContent` takes `wrapItemText` as a third parameter and combines the two class names when it's true.
14
+
15
+ `.optionText > *` used plain `overflow: hidden` until 2026-08-28 (Matt Massey) — it clipped
16
+ descenders (e.g. "g") whenever `text_line-height` is tighter than the font's natural
17
+ ascent+descent. `overflow-clip-margin` gives ink a small bleed allowance while still clipping
18
+ genuinely overflowing text; same project-wide fix as Chip's `CHIP_IMPLEMENTATION_NOTES.md`.
19
+
20
+ ## Missing gap between the input and the open menu (bug fix, Matt Massey, 2026-08-30)
21
+
22
+ MUI's `Autocomplete` sets an inline `margin: 0px` on its own `.MuiAutocomplete-popper`, so the open
23
+ menu rendered flush against the input's bottom border — mantine-adapter's equivalent (`Combobox`,
24
+ built on Mantine's own `Popover`) has an 8px gap there. That gap isn't a Recursica token: it's
25
+ Mantine's own `Popover` untokenized default (`offset: 8` in `@mantine/core`'s `Popover.mjs`), not
26
+ anything mantine-adapter itself wires up — there's no dedicated "menu offset" entry in the token
27
+ schema. Rather than hardcode an unexplained `8px` in adapter-mui-v7, reused
28
+ `--recursica_brand_dimensions_general_default` (also 8px) — the closest real token with a matching
29
+ value — via `slotProps.popper.className` + a new `.popper { margin-top: ...; }` rule (`!important`
30
+ needed: MUI's inline `margin: 0px` otherwise always wins). If the token schema ever adds a real gap
31
+ token for this, prefer it over this one. `Dropdown`'s own MUI `Select`/`MenuProps` popup has the
32
+ identical gap-less behavior, unfixed here — out of scope for this pass, flagged in
33
+ `OPEN_QUESTIONS.txt`.
34
+
35
+ ## Selected Option Highlight (bug fix)
36
+
37
+ There was previously no rule at all for "this option matches the current value" — only the shared neutral hover tint, and only while actually hovered. MUI's `Autocomplete` already stamps `aria-selected="true"` onto the matching option (`useAutocomplete.js`'s `getOptionProps`), and `defaultRenderOption` spreads `liProps` (which includes it) straight onto the `<li>`, so the DOM signal was already there — `.option[aria-selected="true"]` now maps it to the same menu-item selected-state background/text-color tokens Dropdown uses. Needs `!important`: MUI's own `.MuiAutocomplete-listbox .MuiAutocomplete-option[aria-selected="true"]` rule (`Autocomplete.js`) is a two-class descendant selector — higher specificity than this single-class rule — and paints its own default blue tint otherwise, same reasoning as the padding `!important` above. Verified via Playwright: `aria-selected="true"` plus the token background color both land on the correct option after a plain click-select-reopen.