@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,229 @@
1
+ import React, { forwardRef, useEffect, useState } from "react";
2
+ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
3
+ import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
4
+ import {
5
+ DatePicker as MuiDatePicker,
6
+ type DatePickerProps as MuiDatePickerProps,
7
+ type DatePickerSlotProps,
8
+ type DatePickerSlots,
9
+ } from "@mui/x-date-pickers/DatePicker";
10
+ import dayjs, { type Dayjs } from "dayjs";
11
+ import { type ReadOnlyControlProps } from "@recursica/adapter-common";
12
+ import {
13
+ filterStylingProps,
14
+ type RecursicaOverStyled,
15
+ } from "../../utils/filterStylingProps";
16
+ import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
17
+ import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
18
+ import { CalendarIcon } from "./DatePicker.icons";
19
+ import styles from "./DatePicker.module.css";
20
+
21
+ import { type RecursicaDatePickerProps as BaseRecursicaDatePickerProps } from "@recursica/adapter-common";
22
+
23
+ // Default display/entry format (dayjs format string), matching the mantine-adapter's DatePicker.
24
+ const DATE_FORMAT = "MM/DD/YY";
25
+
26
+ function toDayjs(value: Date | null | undefined): Dayjs | null {
27
+ return value ? dayjs(value) : null;
28
+ }
29
+
30
+ export interface RecursicaDatePickerProps
31
+ extends Omit<
32
+ MuiDatePickerProps,
33
+ | "value"
34
+ | "defaultValue"
35
+ | "onChange"
36
+ | "minDate"
37
+ | "maxDate"
38
+ | "format"
39
+ | "slots"
40
+ | "slotProps"
41
+ >,
42
+ Pick<
43
+ RecursicaFormControlWrapperProps,
44
+ | "label"
45
+ | "error"
46
+ | "required"
47
+ | "id"
48
+ | "assistiveText"
49
+ | "assistiveWithIcon"
50
+ | "formLayout"
51
+ | "labelSize"
52
+ | "labelAlignment"
53
+ | "labelOptionalText"
54
+ | "labelWithEditIcon"
55
+ | "onLabelEditClick"
56
+ >,
57
+ ReadOnlyControlProps,
58
+ BaseRecursicaDatePickerProps {
59
+ /** Selected date, matching the mantine-adapter convention of a plain `Date` value. */
60
+ value?: Date | null;
61
+ /** Uncontrolled initial date. */
62
+ defaultValue?: Date | null;
63
+ /** Fires with the new date, or `null` if cleared. */
64
+ onChange?: (value: Date | null) => void;
65
+ minDate?: Date;
66
+ maxDate?: Date;
67
+ /** Overridable component slots — e.g. `slots={{ openPickerIcon: MyIcon }}` to replace the default calendar icon. */
68
+ slots?: DatePickerSlots;
69
+ slotProps?: DatePickerSlotProps;
70
+ /** Caller-provided inline style, passed through to the FormControlWrapper root. */
71
+ style?: React.CSSProperties;
72
+ }
73
+
74
+ export type DatePickerProps = RecursicaOverStyled<RecursicaDatePickerProps>;
75
+
76
+ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
77
+ function DatePicker(props, ref) {
78
+ const {
79
+ overStyled = false,
80
+ formLayout = "stacked",
81
+
82
+ // Label & Wrapper Maps
83
+ labelSize,
84
+ labelAlignment,
85
+ labelOptionalText,
86
+ labelWithEditIcon,
87
+ onLabelEditClick,
88
+
89
+ label,
90
+ assistiveText,
91
+ assistiveWithIcon,
92
+ error,
93
+ required,
94
+ id,
95
+ className,
96
+ style,
97
+ disabled,
98
+ readOnly,
99
+ readOnlyComponent,
100
+ emptyValueComponent,
101
+ value,
102
+ defaultValue,
103
+ onChange,
104
+ minDate,
105
+ maxDate,
106
+ slots,
107
+ slotProps,
108
+ ...rest
109
+ } = props;
110
+
111
+ const sanitizedProps = filterStylingProps(rest, overStyled);
112
+
113
+ // Internal Dayjs value: MUI X's DatePicker only speaks Dayjs (via AdapterDayjs); the public
114
+ // API stays plain `Date` to match the mantine-adapter convention.
115
+ const [internalValue, setInternalValue] = useState<Dayjs | null>(
116
+ () => toDayjs(value) ?? toDayjs(defaultValue) ?? null,
117
+ );
118
+
119
+ useEffect(() => {
120
+ if (value !== undefined) {
121
+ setInternalValue(toDayjs(value));
122
+ }
123
+ }, [value]);
124
+
125
+ const wrapperClass = className
126
+ ? `${styles.layoutOverride} ${className}`
127
+ : styles.layoutOverride;
128
+
129
+ const handleChange = (next: Dayjs | null) => {
130
+ setInternalValue(next);
131
+ onChange?.(next ? next.toDate() : null);
132
+ };
133
+
134
+ const readOnlyValue = (() => {
135
+ const source = value !== undefined ? value : defaultValue;
136
+ return toDayjs(source)?.format(DATE_FORMAT);
137
+ })();
138
+
139
+ // slotProps.field/desktopPaper are typed to also allow a `(ownerState) => props` function
140
+ // form; this adapter only ever merges plain objects (same assumption TextField/DatePicker's
141
+ // mantine counterpart make for consumer-supplied classNames), so narrow to that shape here.
142
+ const consumerFieldProps =
143
+ slotProps?.field && typeof slotProps.field === "object"
144
+ ? (slotProps.field as Record<string, unknown>)
145
+ : undefined;
146
+ const consumerDesktopPaperProps =
147
+ slotProps?.desktopPaper && typeof slotProps.desktopPaper === "object"
148
+ ? (slotProps.desktopPaper as Record<string, unknown>)
149
+ : undefined;
150
+
151
+ return (
152
+ <WithReadOnlyWrapper
153
+ ref={ref}
154
+ className={wrapperClass}
155
+ style={style}
156
+ controlMaxWidth={undefined}
157
+ controlMinWidth={undefined}
158
+ overStyled={overStyled as true}
159
+ formLayout={formLayout}
160
+ labelSize={labelSize}
161
+ labelAlignment={labelAlignment}
162
+ labelOptionalText={labelOptionalText}
163
+ labelWithEditIcon={labelWithEditIcon}
164
+ onLabelEditClick={onLabelEditClick}
165
+ label={label}
166
+ assistiveText={assistiveText}
167
+ assistiveWithIcon={assistiveWithIcon}
168
+ error={error}
169
+ required={required}
170
+ id={id}
171
+ readOnly={readOnly}
172
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
173
+ readOnlyComponent={readOnlyComponent as any}
174
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
175
+ emptyValueComponent={(emptyValueComponent as any) || undefined}
176
+ readOnlyType="text"
177
+ readOnlyValue={readOnlyValue}
178
+ readOnlyNativeProps={props}
179
+ activeComponent={
180
+ /* Naked field execution safely decoupled from MUI X's own label/error macro handling,
181
+ same convention as TimePicker.tsx. Unlike TimePicker, the popup calendar IS used here
182
+ (and token-styled below) — see DATEPICKER_IMPLEMENTATION_NOTES.md. */
183
+ <div className={styles.root} data-error={error ? "true" : undefined}>
184
+ <LocalizationProvider dateAdapter={AdapterDayjs}>
185
+ <MuiDatePicker
186
+ {...(sanitizedProps as unknown as Partial<MuiDatePickerProps>)}
187
+ value={internalValue}
188
+ onChange={handleChange}
189
+ disabled={disabled}
190
+ format={DATE_FORMAT}
191
+ minDate={toDayjs(minDate) ?? undefined}
192
+ maxDate={toDayjs(maxDate) ?? undefined}
193
+ slots={{ openPickerIcon: CalendarIcon, ...slots }}
194
+ slotProps={
195
+ {
196
+ ...slotProps,
197
+ field: {
198
+ // Calendar icon opens the picker from the left side of the field, mirroring
199
+ // the mantine-adapter's default `leftSection`; overridable via
200
+ // `slots.openPickerIcon`. Only settable per-field, not at the picker's own
201
+ // top level (MUI X has no top-level `openPickerButtonPosition` prop).
202
+ openPickerButtonPosition: "start",
203
+ ...consumerFieldProps,
204
+ className: consumerFieldProps?.className
205
+ ? `${styles.field} ${consumerFieldProps.className as string}`
206
+ : styles.field,
207
+ },
208
+ // The popup surface is portaled to document.body, outside this component's own
209
+ // DOM subtree, so — same constraint mantine-adapter's `popoverProps.classNames`
210
+ // documents — it can only be reached by handing it a className directly, not a
211
+ // descendant CSS selector.
212
+ desktopPaper: {
213
+ ...consumerDesktopPaperProps,
214
+ className: consumerDesktopPaperProps?.className
215
+ ? `${styles.dropdown} ${consumerDesktopPaperProps.className as string}`
216
+ : styles.dropdown,
217
+ },
218
+ } as DatePickerSlotProps
219
+ }
220
+ />
221
+ </LocalizationProvider>
222
+ </div>
223
+ }
224
+ />
225
+ );
226
+ },
227
+ );
228
+
229
+ DatePicker.displayName = "DatePicker";
@@ -0,0 +1,49 @@
1
+ # DatePicker - Usage Guide
2
+
3
+ This document describes how to integrate and use the `DatePicker` component in your projects using `@recursica/adapter-mui-v7`.
4
+
5
+ ---
6
+
7
+ ## 1. Import Reference
8
+
9
+ ```tsx
10
+ import { DatePicker } from "@recursica/adapter-mui-v7";
11
+ ```
12
+
13
+ ---
14
+
15
+ ## 2. Basic Example
16
+
17
+ ```tsx
18
+ import React from "react";
19
+ import { DatePicker } from "@recursica/adapter-mui-v7";
20
+
21
+ export default function Demo() {
22
+ return <DatePicker label="Select Date" />;
23
+ }
24
+ ```
25
+
26
+ ---
27
+
28
+ ## 3. Design System Integration
29
+
30
+ All Recursica components in the `@recursica/adapter-mui-v7` package adhere strictly to design system spacing, scaling, and behavior patterns.
31
+
32
+ > [!IMPORTANT]
33
+ >
34
+ > - **Anti-override protection**: Rogues style injections (like inline `style` or arbitrary `className`) are automatically blocked by our prop layer unless `overStyled={true}` is explicitly provided.
35
+ > - **No Direct Layers**: Do not pass a `layer` prop to this component. To place it on a specific visual layer, wrap it in a `<Layer layer={0|1|2|3}>` component natively.
36
+ > - **Variables and Theming**: Styling is entirely determined by local CSS variables defined in `recursica_variables_scoped.css` and mapped in the component's CSS module.
37
+
38
+ ---
39
+
40
+ ## 4. Key Integration Features & Constraints
41
+
42
+ ## Structural Constraints
43
+
44
+ 1. **Value Type**: `value`/`defaultValue`/`onChange` all speak plain `Date` objects (not MUI X's native `Dayjs`), matching the mantine-adapter's DatePicker convention — conversion to/from `Dayjs` happens internally.
45
+ 2. **Read-Only Rendering**: When rendered in read-only mode, the selected date is displayed formatted as `MM/DD/YY`. If you need custom date formatting, pass a `readOnlyComponent` prop to control how the value is rendered.
46
+ 3. **Calendar Popover Styling**: The UI Kit exports no calendar-specific tokens (surface, selected day, hover, today, in-range), so the calendar reuses the closest existing tokens — see `DATEPICKER_IMPLEMENTATION_NOTES.md` for the exact mapping, mirrored 1:1 from the mantine-adapter. The header's prev/next arrows and month-view toggle are styled as Recursica `text`-variant buttons.
47
+ 4. **Typing vs. Popover Entry**: Unlike the mantine-adapter (popover-only selection), MUI X's field supports typing a date directly into its masked `MM/DD/YY` segments, in addition to picking from the popup calendar.
48
+ 5. **Default Display/Entry Format**: `MM/DD/YY` (e.g. `08/19/26`), matching the mantine-adapter; pass your own `format` (a `dayjs` format string) via the standard MUI X `DatePicker` props to override.
49
+ 6. **Default Leading Icon**: A calendar icon opens the picker from the start of the field by default; pass `slots={{ openPickerIcon: MyIcon }}` to override it.
@@ -0,0 +1 @@
1
+ export * from "./DatePicker";
@@ -0,0 +1,168 @@
1
+ import { forwardRef } from "react";
2
+ import {
3
+ Select as MuiSelect,
4
+ type SelectProps as MuiSelectProps,
5
+ MenuItem,
6
+ } from "@mui/material";
7
+ import {
8
+ type RecursicaComboboxData,
9
+ normalizeComboboxData,
10
+ } from "@recursica/adapter-common";
11
+ import {
12
+ filterStylingProps,
13
+ omitUnsupportedProps,
14
+ type RecursicaOverStyled,
15
+ } from "../../utils/filterStylingProps";
16
+ import { renderRichOptionContent } from "../../utils/renderRichOption";
17
+ import styles from "./Dropdown.module.css";
18
+
19
+ /**
20
+ * Bare, unwrapped Select — no `FormControlWrapper`/`WithReadOnlyWrapper`, no label/assistiveText/
21
+ * error/required. Tied to the same `Dropdown.module.css` variables/classes as the public
22
+ * `Dropdown` component, so it looks identical, but is meant to be embedded inside another
23
+ * component that already owns its own `FormControlWrapper` (e.g. `TimePicker`'s AM/PM control) —
24
+ * nesting the full `Dropdown` there would double up `FormControl`/`FormControlLayout` wrapping.
25
+ *
26
+ * Not exported from this folder's `index.ts` — internal use only. Import it directly:
27
+ * `import { BareDropdown } from "../Dropdown/BareDropdown"`.
28
+ */
29
+ export interface BareDropdownProps
30
+ extends Omit<
31
+ MuiSelectProps,
32
+ "size" | "variant" | "classes" | "error" | "onChange"
33
+ > {
34
+ data: RecursicaComboboxData;
35
+ /** Normalized to just the selected value, unlike MUI's raw (event, child) Select onChange. */
36
+ onChange?: (value: string | null) => void;
37
+ /** Applies the error visual state (via `data-error`) — no error message is rendered here. */
38
+ error?: boolean;
39
+ }
40
+
41
+ export type BareDropdownComponentProps = RecursicaOverStyled<BareDropdownProps>;
42
+
43
+ export const BareDropdown = forwardRef<
44
+ HTMLInputElement,
45
+ BareDropdownComponentProps
46
+ >(function BareDropdown(props, ref) {
47
+ const {
48
+ overStyled = false,
49
+ disabled,
50
+ data,
51
+ onChange,
52
+ className,
53
+ value,
54
+ defaultValue,
55
+ error,
56
+ ...rest
57
+ } = props;
58
+ // Props this component intentionally doesn't support — deleted at runtime so they can't leak
59
+ // through even if a caller forces them via plain JavaScript, bypassing the Omit<> above.
60
+ const UNSUPPORTED_PROPS = [
61
+ "size", // Recursica controls sizing via design tokens, not MUI's native small/medium size
62
+ "variant", // Recursica styles the naked select directly; MUI's standard/filled/outlined unused
63
+ "classes", // Recursica computes its own classes object below; caller's would silently clobber it
64
+ ] as const satisfies readonly (keyof MuiSelectProps)[];
65
+
66
+ const sanitizedProps = omitUnsupportedProps(
67
+ filterStylingProps(rest, overStyled),
68
+ UNSUPPORTED_PROPS,
69
+ );
70
+ const restRecord = sanitizedProps as Record<string, unknown>;
71
+
72
+ const mergedClassName = className
73
+ ? `${styles.root} ${className}`
74
+ : styles.root;
75
+
76
+ const selectedValue = value ?? defaultValue;
77
+
78
+ const optionClassNames = {
79
+ optionContent: styles.optionContent,
80
+ optionIcon: styles.optionIcon,
81
+ optionText: styles.optionText,
82
+ optionTextWrap: styles.optionTextWrap,
83
+ optionSupportingText: styles.optionSupportingText,
84
+ };
85
+
86
+ // See Dropdown.tsx's identical use of `normalizeComboboxData` (adapter-common).
87
+ const normalizedData = normalizeComboboxData(data) ?? [];
88
+
89
+ const renderOptions = () =>
90
+ normalizedData.map((item, index) => {
91
+ if (typeof item === "string") {
92
+ return (
93
+ <MenuItem
94
+ key={`${item}-${index}`}
95
+ value={item}
96
+ className={styles.option}
97
+ // Dropdown.module.css's own selected-state tint (`.option[data-selected="true"]`) needs
98
+ // this explicitly — MUI's own `Mui-selected` class carries its default primary-color
99
+ // tint instead, which is what shows through without it.
100
+ data-selected={item === selectedValue ? "true" : undefined}
101
+ >
102
+ {item}
103
+ </MenuItem>
104
+ );
105
+ }
106
+ return (
107
+ <MenuItem
108
+ key={`${item.value}-${index}`}
109
+ value={item.value}
110
+ disabled={item.disabled}
111
+ className={styles.option}
112
+ data-selected={item.value === selectedValue ? "true" : undefined}
113
+ >
114
+ {renderRichOptionContent(item, optionClassNames)}
115
+ </MenuItem>
116
+ );
117
+ });
118
+
119
+ // See Dropdown.tsx's identical `renderValue` — keeps the closed field showing just the plain
120
+ // label now that a MenuItem's children can be a rich icon+label+supportingText row.
121
+ const renderValue = (selected: unknown) => {
122
+ if (selected === "" || selected === undefined || selected === null) {
123
+ return "";
124
+ }
125
+ const match = normalizedData.find((item) =>
126
+ typeof item === "string" ? item === selected : item.value === selected,
127
+ );
128
+ if (!match) return "";
129
+ return typeof match === "string" ? match : match.label;
130
+ };
131
+
132
+ return (
133
+ <MuiSelect
134
+ ref={ref}
135
+ {...(sanitizedProps as unknown as MuiSelectProps)}
136
+ disabled={disabled}
137
+ value={value}
138
+ defaultValue={defaultValue}
139
+ onChange={(event) => onChange?.((event.target.value as string) ?? null)}
140
+ displayEmpty
141
+ renderValue={renderValue}
142
+ error={!!error}
143
+ className={mergedClassName}
144
+ classes={{
145
+ select: styles.input,
146
+ icon: styles.icon,
147
+ }}
148
+ MenuProps={{
149
+ classes: { paper: styles.dropdown },
150
+ }}
151
+ // Dropdown.module.css's error/disabled state rules key off `.root[data-error]`/
152
+ // `[data-disabled]` (the outer Select element, matching mergedClassName above) —
153
+ // `inputProps` only reaches the nested accessibility <input>, which that selector never
154
+ // matches, so these need to be set here too (mirrors the same fix in Dropdown.tsx).
155
+ data-disabled={disabled ? "true" : undefined}
156
+ data-error={error ? "true" : undefined}
157
+ inputProps={{
158
+ "data-disabled": disabled ? "true" : undefined,
159
+ "data-error": error ? "true" : undefined,
160
+ ...(restRecord.inputProps as Record<string, unknown>),
161
+ }}
162
+ >
163
+ {renderOptions()}
164
+ </MuiSelect>
165
+ );
166
+ });
167
+
168
+ BareDropdown.displayName = "BareDropdown";
@@ -0,0 +1,45 @@
1
+ # Dropdown 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). `Dropdown.tsx` and `BareDropdown.tsx` both build `MenuItem` children directly from `data` (there's no Mantine-style `renderOption` indirection here), so rendering the new fields is a straight change to that existing per-item mapping — `renderRichOptionContent` (`../../utils/renderRichOption.tsx`, shared with `Autocomplete`) renders `leadingIcon`+`label`+`supportingText` when either new field is present, or just `label` otherwise. 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` to stack under it.
6
+
7
+ `label` on the shared type is optional (falls back to `value`) — both components run `data` through adapter-common's `normalizeComboboxData` first (`const normalizedData = normalizeComboboxData(data)`), so every downstream read of `item.label` is a real string, with no per-call-site `?? value` fallback needed.
8
+
9
+ MUI's closed-field display has no separate slot analogous to Mantine's `option.label` — without a `renderValue`, MUI shows whichever `MenuItem`'s children matched the selected value, which would leak the rich icon/supporting-text row into the closed field. Both components now pass a `renderValue` that looks the selected item back up by value and returns its plain `label`, keeping the closed field a single line of text regardless of what the open dropdown renders.
10
+
11
+ New CSS classes (`.optionContent`/`.optionIcon`/`.optionText`/`.optionSupportingText`) in `Dropdown.module.css` reuse the menu-item component's icon/supporting-text tokens, matching the mantine-adapter's equivalent addition — no dedicated dropdown-option tokens exist for either.
12
+
13
+ ## `wrapItemText`
14
+
15
+ `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. `Dropdown.tsx` exposes this as a public prop; `BareDropdown.tsx` (internal-only, not part of the public `Dropdown`/`AutoComplete` API this was requested for) doesn't take the prop and always truncates.
16
+
17
+ `.optionText > *` used plain `overflow: hidden` until 2026-08-28 (Matt Massey) — it clipped
18
+ descenders (e.g. "g") whenever `text_line-height` is tighter than the font's natural
19
+ ascent+descent. `overflow-clip-margin` gives ink a small bleed allowance while still clipping
20
+ genuinely overflowing text; same project-wide fix as Chip's `CHIP_IMPLEMENTATION_NOTES.md`.
21
+
22
+ ## Missing placeholder (bug fix, Matt Massey, 2026-08-30)
23
+
24
+ `placeholder` (a real prop on `RecursicaDropdownProps` via `adapter-common`) was accepted but
25
+ silently did nothing — it fell through to `...rest`/`sanitizedProps` and got spread onto
26
+ `<MuiSelect>`, which only forwards it to its own hidden accessibility `<input>` (invisible to the
27
+ user); MUI's `Select` is not a native text `<input>`, so it has no `::placeholder` rendering path
28
+ of its own. mantine-adapter's `Select` supports `placeholder` natively, so the equivalent bug never
29
+ existed there. Fixed by destructuring `placeholder` explicitly and rendering it from `renderValue`
30
+ when the field is empty, wrapped in a new `.placeholder` class (same opacity treatment as
31
+ `.input::placeholder`) since a `<span>` inside a non-input element has no pseudo-element to target.
32
+
33
+ The `ui-kit-dropdown--with-rich-options`/`-wrapped` stories were also flagged as "text isn't
34
+ vertically centered" — with no placeholder rendering, MUI's empty `.MuiSelect-select` fell back to
35
+ its own zero-width-space filler content (`&#8203;`, used internally to preserve the box's height),
36
+ which doesn't establish the same line box a real placeholder string does. Rendering the actual
37
+ placeholder text resolved this too — verified via screenshot, no separate CSS change needed.
38
+
39
+ ## Missing input-to-menu gap (Matt Massey, ROUND 2 2026-08-31)
40
+
41
+ Same gap AutoComplete had: MUI's Select renders its open menu flush against the input, no offset
42
+ token exists in the schema for it either. Fixed with the identical technique — `margin-top: var(
43
+ --recursica_brand_dimensions_general_default)` on `.dropdown` (the `MenuProps.classes.paper`
44
+ target). Unlike AutoComplete's Popper, Select's menu is a Popover, which positions via computed
45
+ `top`/`left` rather than an inline `margin: 0`, so no `!important` was needed here.
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+
3
+ /**
4
+ * Chevron rendered in the right section alongside the clear button (item 3a). Only used for that
5
+ * combined case — MUI's own default `IconComponent` (`ArrowDropDown`) is left untouched everywhere
6
+ * else, so this is a hand-rolled copy of the exact same MUI glyph path, not a new icon design.
7
+ */
8
+ export function ChevronIcon(props: React.SVGProps<SVGSVGElement>) {
9
+ return (
10
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden {...props}>
11
+ <path d="M7 10l5 5 5-5z" />
12
+ </svg>
13
+ );
14
+ }
15
+
16
+ /** Clear ("x") icon for the clearable Dropdown's clear button (item 3a). */
17
+ export function ClearIcon(props: React.SVGProps<SVGSVGElement>) {
18
+ return (
19
+ <svg
20
+ viewBox="0 0 24 24"
21
+ fill="none"
22
+ stroke="currentColor"
23
+ strokeWidth="2"
24
+ strokeLinecap="round"
25
+ strokeLinejoin="round"
26
+ aria-hidden
27
+ {...props}
28
+ >
29
+ <line x1="18" y1="6" x2="6" y2="18" />
30
+ <line x1="6" y1="6" x2="18" y2="18" />
31
+ </svg>
32
+ );
33
+ }