@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,435 @@
1
+ import React, { forwardRef, useState, useEffect, useRef } from "react";
2
+ import {
3
+ Slider as MuiSlider,
4
+ type SliderProps as MuiSliderProps,
5
+ } from "@mui/material";
6
+ import { type ReadOnlyControlProps } from "@recursica/adapter-common";
7
+ import {
8
+ filterStylingProps,
9
+ omitUnsupportedProps,
10
+ mergeClassNames,
11
+ type RecursicaOverStyled,
12
+ } from "../../utils/filterStylingProps";
13
+ import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
14
+ import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
15
+
16
+ import styles from "./Slider.module.css";
17
+
18
+ import { type RecursicaSliderProps as BaseRecursicaSliderProps } from "@recursica/adapter-common";
19
+
20
+ export interface RecursicaSliderProps
21
+ extends Omit<
22
+ MuiSliderProps,
23
+ | "size"
24
+ | "color"
25
+ | "classes"
26
+ | "onChange"
27
+ | "onChangeCommitted"
28
+ | "value"
29
+ | "defaultValue"
30
+ >,
31
+ Omit<
32
+ RecursicaFormControlWrapperProps,
33
+ | "controlMaxWidth"
34
+ | "controlMinWidth"
35
+ | "error"
36
+ | "required"
37
+ | "withAsterisk"
38
+ | keyof MuiSliderProps
39
+ >,
40
+ ReadOnlyControlProps,
41
+ BaseRecursicaSliderProps {}
42
+
43
+ export type SliderProps = RecursicaOverStyled<RecursicaSliderProps>;
44
+
45
+ /**
46
+ * Custom Read-Only visual representation of the Slider value.
47
+ * Utilizes component-specific read-only typography variables. Renders a "lower – upper" pair
48
+ * when the value is a range tuple.
49
+ */
50
+ const SliderReadOnlyValue: React.FC<{ value: number | [number, number] }> = ({
51
+ value,
52
+ }) => {
53
+ const display = Array.isArray(value) ? `${value[0]} – ${value[1]}` : value;
54
+ return <div className={styles.readOnlyValue}>{display}</div>;
55
+ };
56
+
57
+ /**
58
+ * Recursica Slider component wrapping Mui's Slider.
59
+ *
60
+ * MUI's own `Slider` already renders two thumbs natively when given a tuple `value`, so range
61
+ * mode here is a typing/handler concern rather than a different underlying component (contrast
62
+ * with the mantine-adapter, which swaps in Mantine's separate `RangeSlider`).
63
+ *
64
+ * Implements a bidirectional text input field next to the slider track, responsive layouts,
65
+ * custom typography-bound min/max labels (optionally overridden via `minLabel`/`maxLabel`),
66
+ * optional leading/trailing icons, and an explicit read-only layout.
67
+ */
68
+ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
69
+ function Slider(props, ref) {
70
+ const {
71
+ overStyled = false,
72
+ formLayout = "stacked",
73
+
74
+ // Label & Wrapper Maps
75
+ labelSize,
76
+ labelAlignment,
77
+ labelOptionalText,
78
+ labelWithEditIcon,
79
+ labelActionArea,
80
+ onLabelEditClick,
81
+
82
+ label,
83
+ tooltipLabel,
84
+ assistiveText,
85
+ assistiveWithIcon,
86
+ error,
87
+ required,
88
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
89
+ withAsterisk,
90
+ id,
91
+ className,
92
+ style,
93
+ disabled,
94
+ readOnly,
95
+ readOnlyComponent,
96
+ emptyValueComponent,
97
+ value,
98
+ defaultValue,
99
+ icon,
100
+ trailingIcon,
101
+ showInput = false,
102
+ showMinMaxLabels = true,
103
+ min = 0,
104
+ max = 100,
105
+ minLabel,
106
+ maxLabel,
107
+ step = 1,
108
+ onChange,
109
+ onChangeEnd,
110
+ ...rest
111
+ } = props;
112
+
113
+ // Bidirectional state linking the slider track value to the input field string
114
+ // representation. A `[number, number]` value/defaultValue switches the component into
115
+ // two-thumb range mode — MUI's own Slider already renders two thumbs for a tuple value.
116
+ type SliderValue = number | [number, number];
117
+
118
+ const [internalValue, setInternalValue] = useState<SliderValue>(() => {
119
+ if (value !== undefined) return value;
120
+ if (defaultValue !== undefined) return defaultValue;
121
+ return min;
122
+ });
123
+
124
+ const resolvedValue: SliderValue =
125
+ value !== undefined ? value : internalValue;
126
+ const isRange = Array.isArray(resolvedValue);
127
+
128
+ const [inputValue, setInputValue] = useState<string | [string, string]>(
129
+ () =>
130
+ Array.isArray(resolvedValue)
131
+ ? [resolvedValue[0].toString(), resolvedValue[1].toString()]
132
+ : resolvedValue.toString(),
133
+ );
134
+
135
+ // Synchronize text input(s) whenever the slider value changes
136
+ useEffect(() => {
137
+ setInputValue(
138
+ Array.isArray(resolvedValue)
139
+ ? [resolvedValue[0].toString(), resolvedValue[1].toString()]
140
+ : resolvedValue.toString(),
141
+ );
142
+ }, [resolvedValue]);
143
+
144
+ const handleValueChange = (_e: Event, val: number | number[]) => {
145
+ const normalized: SliderValue = Array.isArray(val)
146
+ ? [val[0], val[1]]
147
+ : val;
148
+ if (value === undefined) {
149
+ setInternalValue(normalized);
150
+ }
151
+ onChange?.(normalized);
152
+ };
153
+
154
+ const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
155
+ const valStr = e.target.value;
156
+ setInputValue(valStr);
157
+
158
+ const parsed = parseFloat(valStr);
159
+ if (!isNaN(parsed)) {
160
+ // Clamp input value to bounds
161
+ const clamped = Math.max(min, Math.min(max, parsed));
162
+ handleValueChange(null as unknown as Event, clamped);
163
+ }
164
+ };
165
+
166
+ const handleInputBlur = () => {
167
+ setInputValue((resolvedValue as number).toString());
168
+ };
169
+
170
+ // Range-mode input handlers: each bound clamps against the other thumb rather than the
171
+ // shared min/max, so the lower thumb can never cross the upper one and vice versa.
172
+ const handleLowerInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
173
+ const current = resolvedValue as [number, number];
174
+ const valStr = e.target.value;
175
+ setInputValue([valStr, current[1].toString()]);
176
+
177
+ const parsed = parseFloat(valStr);
178
+ if (!isNaN(parsed)) {
179
+ const clamped = Math.max(min, Math.min(current[1], parsed));
180
+ handleValueChange(null as unknown as Event, [clamped, current[1]]);
181
+ }
182
+ };
183
+
184
+ const handleUpperInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
185
+ const current = resolvedValue as [number, number];
186
+ const valStr = e.target.value;
187
+ setInputValue([current[0].toString(), valStr]);
188
+
189
+ const parsed = parseFloat(valStr);
190
+ if (!isNaN(parsed)) {
191
+ const clamped = Math.max(current[0], Math.min(max, parsed));
192
+ handleValueChange(null as unknown as Event, [current[0], clamped]);
193
+ }
194
+ };
195
+
196
+ const handleRangeInputBlur = () => {
197
+ const current = resolvedValue as [number, number];
198
+ setInputValue([current[0].toString(), current[1].toString()]);
199
+ };
200
+
201
+ // Props this component intentionally doesn't support — deleted at runtime so they can't leak
202
+ // through even if a caller forces them via plain JavaScript, bypassing the Omit<> above.
203
+ const UNSUPPORTED_PROPS = [
204
+ "size", // Recursica controls sizing via design tokens, not MUI's native small/medium size
205
+ "color", // Colors are token-driven; MUI's native palette isn't exposed
206
+ ] as const satisfies readonly (keyof MuiSliderProps)[];
207
+
208
+ const sanitizedProps = omitUnsupportedProps(
209
+ filterStylingProps(rest, overStyled),
210
+ UNSUPPORTED_PROPS,
211
+ );
212
+ const restRecord = sanitizedProps as Record<string, unknown>;
213
+
214
+ // MUI always programmatically re-focuses its hidden native input on pointer interaction,
215
+ // which browsers' `:focus-visible` heuristic treats as keyboard-visible — unlike Mantine's
216
+ // plain div thumb, where a real click correctly resolves to a non-visible focus. Track
217
+ // pointer-vs-keyboard ourselves so the focus ring only paints for genuine keyboard focus,
218
+ // matching Mantine (a later keypress while still focused reveals the ring, same as native).
219
+ const pointerDownRef = useRef(false);
220
+ const [suppressFocusRing, setSuppressFocusRing] = useState(false);
221
+ const externalOnMouseDown = (sanitizedProps as MuiSliderProps).onMouseDown;
222
+ const externalOnFocus = (sanitizedProps as MuiSliderProps).onFocus;
223
+ const externalOnBlur = (sanitizedProps as MuiSliderProps).onBlur;
224
+ const externalOnKeyDown = (sanitizedProps as MuiSliderProps).onKeyDown;
225
+
226
+ const handleThumbMouseDown = (e: React.MouseEvent<HTMLSpanElement>) => {
227
+ pointerDownRef.current = true;
228
+ externalOnMouseDown?.(e);
229
+ };
230
+ const handleThumbFocus = (e: React.FocusEvent<HTMLSpanElement>) => {
231
+ setSuppressFocusRing(pointerDownRef.current);
232
+ pointerDownRef.current = false;
233
+ externalOnFocus?.(e);
234
+ };
235
+ const handleThumbBlur = (e: React.FocusEvent<HTMLSpanElement>) => {
236
+ setSuppressFocusRing(false);
237
+ externalOnBlur?.(e);
238
+ };
239
+ const handleThumbKeyDown = (e: React.KeyboardEvent<HTMLSpanElement>) => {
240
+ setSuppressFocusRing(false);
241
+ externalOnKeyDown?.(e);
242
+ };
243
+
244
+ // Securely map core native blocks down ensuring nested CSS modules map precisely. Note MUI's
245
+ // actual prop is "classes", not "classNames" (that's Mantine's naming) — this used to read
246
+ // the wrong key, silently no-op-ing any caller-supplied classes. The caller-facing slot names
247
+ // below (root/track/bar/thumb/mark/markLabel) mirror the mantine-adapter's own Slider
248
+ // classNames slots, translated to MUI's real classes slot names (root/rail/track/thumb/...).
249
+ const callerClasses = restRecord.classes as
250
+ | Partial<Record<string, string>>
251
+ | undefined;
252
+ const mergedClassNames = mergeClassNames(
253
+ {
254
+ root: styles.sliderRoot,
255
+ rail: styles.sliderTrack,
256
+ track: styles.sliderBar,
257
+ thumb: styles.sliderThumb,
258
+ mark: styles.sliderMark,
259
+ markLabel: styles.sliderMarkLabel,
260
+ valueLabel: styles.sliderTooltip,
261
+ },
262
+ callerClasses && {
263
+ root: callerClasses.root,
264
+ rail: callerClasses.track,
265
+ track: callerClasses.bar,
266
+ thumb: callerClasses.thumb,
267
+ mark: callerClasses.mark,
268
+ markLabel: callerClasses.markLabel,
269
+ },
270
+ );
271
+
272
+ const wrapperClass = className
273
+ ? `${styles.layoutOverride} ${className}`
274
+ : styles.layoutOverride;
275
+
276
+ const leadingIcon = icon ? (
277
+ <span className={styles.iconWrapper} aria-hidden>
278
+ {icon}
279
+ </span>
280
+ ) : null;
281
+
282
+ const trailingIconEl = trailingIcon ? (
283
+ <span className={styles.iconWrapper} aria-hidden>
284
+ {trailingIcon}
285
+ </span>
286
+ ) : null;
287
+
288
+ // Duplicates the raw numeric value next to the track by default; when `tooltipLabel` is a
289
+ // formatter, reuse it here too so both displays agree instead of one showing raw numbers.
290
+ // Range mode formats each thumb independently and joins them with an en dash.
291
+ const displayValue = Array.isArray(resolvedValue)
292
+ ? typeof tooltipLabel === "function"
293
+ ? `${tooltipLabel(resolvedValue[0])} – ${tooltipLabel(resolvedValue[1])}`
294
+ : `${resolvedValue[0]} – ${resolvedValue[1]}`
295
+ : typeof tooltipLabel === "function"
296
+ ? tooltipLabel(resolvedValue)
297
+ : resolvedValue;
298
+
299
+ return (
300
+ <WithReadOnlyWrapper
301
+ ref={ref}
302
+ className={wrapperClass}
303
+ style={style as React.CSSProperties}
304
+ controlMaxWidth={undefined}
305
+ controlMinWidth={undefined}
306
+ overStyled={overStyled as true}
307
+ formLayout={formLayout}
308
+ labelSize={labelSize}
309
+ labelAlignment={labelAlignment}
310
+ labelOptionalText={labelOptionalText}
311
+ labelWithEditIcon={labelWithEditIcon}
312
+ labelActionArea={labelActionArea}
313
+ onLabelEditClick={onLabelEditClick}
314
+ label={label}
315
+ assistiveText={assistiveText}
316
+ assistiveWithIcon={assistiveWithIcon}
317
+ error={!!error}
318
+ required={required}
319
+ id={id}
320
+ readOnly={readOnly}
321
+ readOnlyComponent={readOnlyComponent || SliderReadOnlyValue}
322
+ emptyValueComponent={emptyValueComponent}
323
+ readOnlyType="text"
324
+ readOnlyValue={resolvedValue}
325
+ readOnlyNativeProps={{ value: resolvedValue }}
326
+ activeComponent={
327
+ <div
328
+ className={styles.sliderContainer}
329
+ data-form-layout={formLayout}
330
+ data-disabled={disabled ? "true" : undefined}
331
+ data-error={error ? "true" : undefined}
332
+ data-suppress-focus-ring={suppressFocusRing ? "true" : undefined}
333
+ >
334
+ {isRange && showInput && (
335
+ <input
336
+ type="number"
337
+ className={styles.inputField}
338
+ value={(inputValue as [string, string])[0]}
339
+ onChange={handleLowerInputChange}
340
+ onBlur={handleRangeInputBlur}
341
+ min={min}
342
+ max={(resolvedValue as [number, number])[1]}
343
+ step={step ?? undefined}
344
+ disabled={disabled}
345
+ data-error={error ? "true" : undefined}
346
+ aria-label="Minimum value"
347
+ />
348
+ )}
349
+
350
+ {leadingIcon}
351
+
352
+ {showMinMaxLabels && (
353
+ <span className={styles.minMaxGuide}>{minLabel ?? min}</span>
354
+ )}
355
+
356
+ <div className={styles.sliderTrackWrapper}>
357
+ <MuiSlider
358
+ {...(sanitizedProps as unknown as MuiSliderProps)}
359
+ classes={mergedClassNames}
360
+ disabled={disabled}
361
+ value={resolvedValue}
362
+ onChange={handleValueChange}
363
+ onMouseDown={handleThumbMouseDown}
364
+ onFocus={handleThumbFocus}
365
+ onBlur={handleThumbBlur}
366
+ onKeyDown={handleThumbKeyDown}
367
+ onChangeCommitted={
368
+ onChangeEnd as unknown as (
369
+ event: Event | React.SyntheticEvent,
370
+ value: number | number[],
371
+ ) => void
372
+ }
373
+ min={min}
374
+ max={max}
375
+ step={step}
376
+ valueLabelDisplay={tooltipLabel === null ? "off" : "auto"}
377
+ valueLabelFormat={
378
+ typeof tooltipLabel === "function"
379
+ ? (tooltipLabel as unknown as (
380
+ value: number,
381
+ index: number,
382
+ ) => React.ReactNode)
383
+ : undefined
384
+ }
385
+ />
386
+ </div>
387
+
388
+ <div className={styles.rightGuideContainer}>
389
+ {!showInput && (
390
+ <span className={styles.currentValue}>{displayValue}</span>
391
+ )}
392
+ {showMinMaxLabels && (
393
+ <span className={styles.minMaxGuide}>{maxLabel ?? max}</span>
394
+ )}
395
+ </div>
396
+
397
+ {trailingIconEl}
398
+
399
+ {showInput &&
400
+ (isRange ? (
401
+ <input
402
+ type="number"
403
+ className={styles.inputField}
404
+ value={(inputValue as [string, string])[1]}
405
+ onChange={handleUpperInputChange}
406
+ onBlur={handleRangeInputBlur}
407
+ min={(resolvedValue as [number, number])[0]}
408
+ max={max}
409
+ step={step ?? undefined}
410
+ disabled={disabled}
411
+ data-error={error ? "true" : undefined}
412
+ aria-label="Maximum value"
413
+ />
414
+ ) : (
415
+ <input
416
+ type="number"
417
+ className={styles.inputField}
418
+ value={inputValue as string}
419
+ onChange={handleInputChange}
420
+ onBlur={handleInputBlur}
421
+ min={min}
422
+ max={max}
423
+ step={step ?? undefined}
424
+ disabled={disabled}
425
+ data-error={error ? "true" : undefined}
426
+ />
427
+ ))}
428
+ </div>
429
+ }
430
+ />
431
+ );
432
+ },
433
+ );
434
+
435
+ Slider.displayName = "Slider";
@@ -0,0 +1,56 @@
1
+ # Slider - Usage Guide
2
+
3
+ This document describes how to integrate and use the `Slider` component in your projects using `@recursica/adapter-mui-v7`.
4
+
5
+ ---
6
+
7
+ ## 1. Import Reference
8
+
9
+ ```tsx
10
+ import { Slider } from "@recursica/adapter-mui-v7";
11
+ ```
12
+
13
+ ---
14
+
15
+ ## 2. Basic Example
16
+
17
+ ```tsx
18
+ import React from "react";
19
+ import { Slider } from "@recursica/adapter-mui-v7";
20
+
21
+ export default function Demo() {
22
+ return <Slider defaultValue={50} min={0} max={100} label="Volume" />;
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
+ The `label` prop is passed through to the surrounding form label rather than MUI's dragging tooltip; use `tooltipLabel` to set the label shown while dragging. When `showInput` is enabled, a numeric text input is rendered alongside the track and stays in sync with the slider's value. Set `showMinMaxLabels` to `false` to hide the min/max guides shown at either end of the track. Otherwise, the current value is displayed near the track instead — pass `tooltipLabel` as a formatter function (`(value) => ReactNode`) and that same formatter is reused for this display, instead of always showing the raw number. `minLabel`/`maxLabel` override the text shown at either end of the track (defaults to the numeric `min`/`max`). `icon` renders a leading icon next to the track; `trailingIcon` renders one on the opposite side, rendered right after the max label and before the numeric input.
43
+
44
+ ### Range Mode
45
+
46
+ Pass a `[number, number]` tuple as `value`/`defaultValue` to render a two-thumb range slider — `onChange`/`onChangeEnd` are then called with a `[number, number]` tuple instead of a `number`. With `showInput` enabled, a second numeric input for the upper bound appears after the trailing icon, with the lower-bound input before the leading icon:
47
+
48
+ ```tsx
49
+ <Slider
50
+ label="Price Range"
51
+ defaultValue={[20, 80]}
52
+ min={0}
53
+ max={100}
54
+ onChange={(value) => console.log(value)} // [number, number]
55
+ />
56
+ ```
@@ -0,0 +1 @@
1
+ export * from "./Slider";
@@ -0,0 +1,108 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { Stack } from "./Stack";
4
+ import { Button } from "../Button";
5
+ import { Text } from "../Text/Text";
6
+
7
+ type StackStoryProps = React.ComponentProps<typeof Stack>;
8
+
9
+ const meta: Meta<StackStoryProps> = {
10
+ title: "UI-Kit/Stack",
11
+ component: Stack,
12
+ tags: ["autodocs"],
13
+ parameters: {
14
+ docs: {
15
+ description: {
16
+ component:
17
+ "Stack is a flex vertical layout container that maps directly to Mantine's Stack component allowing safe layout property passing.",
18
+ },
19
+ },
20
+ },
21
+ args: {
22
+ spacing: "rec-default",
23
+ alignItems: "stretch",
24
+ justifyContent: "flex-start",
25
+ },
26
+ argTypes: {
27
+ spacing: {
28
+ control: "select",
29
+ options: [
30
+ "rec-none",
31
+ "rec-sm",
32
+ "rec-default",
33
+ "rec-md",
34
+ "rec-lg",
35
+ "rec-xl",
36
+ "rec-2xl",
37
+ "xs",
38
+ "sm",
39
+ "md",
40
+ "lg",
41
+ "xl",
42
+ ],
43
+ description: "Space between elements",
44
+ },
45
+ alignItems: {
46
+ control: "select",
47
+ options: ["flex-start", "center", "flex-end", "stretch"],
48
+ description: "Align-items property",
49
+ },
50
+ justifyContent: {
51
+ control: "select",
52
+ options: [
53
+ "flex-start",
54
+ "center",
55
+ "flex-end",
56
+ "space-between",
57
+ "space-around",
58
+ ],
59
+ description: "Justify-content property",
60
+ },
61
+ defaultChecked: {
62
+ table: { disable: true },
63
+ },
64
+ },
65
+ };
66
+
67
+ export default meta;
68
+
69
+ type Story = StoryObj<StackStoryProps>;
70
+
71
+ export const Default: Story = {
72
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
73
+ render: ({ withLayer, layer, ...args }: any) => (
74
+ <Stack {...args}>
75
+ <Button variant="solid">Primary Block</Button>
76
+ <Button variant="outline">Secondary Block</Button>
77
+ <Text>Text element within Stack</Text>
78
+ </Stack>
79
+ ),
80
+ };
81
+
82
+ export const StaticGapSmall: Story = {
83
+ args: {
84
+ spacing: "rec-sm",
85
+ },
86
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
87
+ render: ({ withLayer, layer, ...args }: any) => (
88
+ <Stack {...args}>
89
+ <Button variant="solid">Item 1</Button>
90
+ <Button variant="solid">Item 2</Button>
91
+ <Button variant="solid">Item 3</Button>
92
+ </Stack>
93
+ ),
94
+ };
95
+
96
+ export const StaticGapLarge: Story = {
97
+ args: {
98
+ spacing: "rec-xl",
99
+ },
100
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
101
+ render: ({ withLayer, layer, ...args }: any) => (
102
+ <Stack {...args}>
103
+ <Button variant="solid">Item 1</Button>
104
+ <Button variant="solid">Item 2</Button>
105
+ <Button variant="solid">Item 3</Button>
106
+ </Stack>
107
+ ),
108
+ };
@@ -0,0 +1 @@
1
+ // Placeholder for future Stack component tests. Add tests here if/when needed.
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Stack layout wrapper.
3
+ *
4
+ * MUI has a native `Stack`, so this simply passes through its own props (`direction`,
5
+ * `spacing`, `alignItems`, `justifyContent`, etc.) with no Recursica renaming — only
6
+ * `spacing` gains `rec-*` token support via `WithRecursicaSpacing`.
7
+ */
8
+ import { forwardRef } from "react";
9
+ import {
10
+ Stack as MUIStack,
11
+ type StackProps as MUIStackProps,
12
+ } from "@mui/material";
13
+ import {
14
+ SPACING_MAP,
15
+ type OmitSx,
16
+ filterSxProp,
17
+ type WithRecursicaSpacing,
18
+ } from "../../utils/filterStylingProps";
19
+
20
+ export type StackProps = WithRecursicaSpacing<OmitSx<MUIStackProps>>;
21
+
22
+ export const Stack = forwardRef<HTMLDivElement, StackProps>(function Stack(
23
+ { children, spacing = "rec-default", ...rest },
24
+ ref,
25
+ ) {
26
+ const safeProps = filterSxProp(rest as Record<string, unknown>);
27
+ const resolvedSpacing =
28
+ typeof spacing === "string" && spacing in SPACING_MAP
29
+ ? SPACING_MAP[spacing as keyof typeof SPACING_MAP]
30
+ : spacing;
31
+
32
+ return (
33
+ <MUIStack
34
+ ref={ref}
35
+ {...(safeProps as unknown as MUIStackProps)}
36
+ spacing={resolvedSpacing}
37
+ >
38
+ {children}
39
+ </MUIStack>
40
+ );
41
+ });
42
+
43
+ Stack.displayName = "Stack";
@@ -0,0 +1,41 @@
1
+ # Stack - Usage Guide
2
+
3
+ This document describes how to integrate and use the `Stack` component in your projects using `@recursica/adapter-mui-v7`.
4
+
5
+ ---
6
+
7
+ ## 1. Import Reference
8
+
9
+ ```tsx
10
+ import { Stack } from "@recursica/adapter-mui-v7";
11
+ ```
12
+
13
+ ---
14
+
15
+ ## 2. Basic Example
16
+
17
+ ```tsx
18
+ import React from "react";
19
+ import { Stack } from "@recursica/adapter-mui-v7";
20
+
21
+ export default function Demo() {
22
+ return (
23
+ <Stack spacing="md" alignItems="stretch">
24
+ <Text>Item 1</Text>
25
+ <Text>Item 2</Text>
26
+ </Stack>
27
+ );
28
+ }
29
+ ```
30
+
31
+ ---
32
+
33
+ ## 3. Design System Integration
34
+
35
+ All Recursica components in the `@recursica/adapter-mui-v7` package adhere strictly to design system spacing, scaling, and behavior patterns.
36
+
37
+ > [!IMPORTANT]
38
+ >
39
+ > - **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.
40
+ > - **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.
41
+ > - **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.
@@ -0,0 +1 @@
1
+ export * from "./Stack";