@recursica/mantine-adapter 0.9.4 → 0.11.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 (290) hide show
  1. package/.storybook/commonArgTypes.ts +148 -0
  2. package/CHANGELOG.md +94 -0
  3. package/README.md +48 -332
  4. package/dist/index.d.ts +2 -8
  5. package/dist/mantine-adapter.cjs +2 -0
  6. package/dist/mantine-adapter.cjs.map +1 -0
  7. package/dist/mantine-adapter.css +1 -0
  8. package/dist/mantine-adapter.js +1963 -0
  9. package/dist/mantine-adapter.js.map +1 -0
  10. package/dist/src/components/Accordion/Accordion.d.ts +42 -0
  11. package/dist/src/components/Accordion/index.d.ts +1 -0
  12. package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +10 -0
  13. package/dist/src/components/Avatar/Avatar.d.ts +9 -0
  14. package/dist/src/components/Avatar/index.d.ts +1 -0
  15. package/dist/src/components/Badge/Badge.d.ts +8 -0
  16. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +6 -0
  17. package/dist/src/components/Button/Button.d.ts +10 -0
  18. package/dist/src/components/Button/index.d.ts +1 -0
  19. package/dist/src/components/Card/Card.d.ts +38 -0
  20. package/dist/src/components/Checkbox/Checkbox.d.ts +13 -0
  21. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +9 -0
  22. package/dist/src/components/Chip/Chip.d.ts +15 -0
  23. package/dist/src/components/Container/Container.d.ts +18 -0
  24. package/dist/src/components/DatePicker/DatePicker.d.ts +3 -0
  25. package/dist/src/components/Dropdown/Dropdown.d.ts +11 -0
  26. package/dist/src/components/FileInput/FileInput.d.ts +3 -0
  27. package/dist/src/components/FileUpload/FileUpload.d.ts +3 -0
  28. package/dist/src/components/Flex/Flex.d.ts +17 -0
  29. package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +21 -0
  30. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +20 -0
  31. package/dist/src/components/Group/Group.d.ts +17 -0
  32. package/dist/src/components/HoverCard/HoverCard.d.ts +3 -0
  33. package/dist/src/components/Label/Label.d.ts +19 -0
  34. package/dist/src/components/Label/index.d.ts +1 -0
  35. package/dist/src/components/Link/Link.d.ts +3 -0
  36. package/dist/src/components/Loader/Loader.d.ts +10 -0
  37. package/dist/src/components/Menu/Menu.d.ts +3 -0
  38. package/dist/src/components/Modal/Modal.d.ts +3 -0
  39. package/dist/src/components/NumberInput/NumberInput.d.ts +3 -0
  40. package/dist/src/components/Pagination/Pagination.d.ts +3 -0
  41. package/dist/src/components/Panel/Panel.d.ts +3 -0
  42. package/dist/src/components/Popover/Popover.d.ts +3 -0
  43. package/dist/src/components/Radio/Radio.d.ts +13 -0
  44. package/dist/src/components/Radio/RadioGroup.d.ts +9 -0
  45. package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
  46. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +20 -0
  47. package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
  48. package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
  49. package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +28 -0
  50. package/dist/src/components/ReadOnlyField/index.d.ts +5 -0
  51. package/dist/src/components/Search/Search.d.ts +3 -0
  52. package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  53. package/dist/src/components/Slider/Slider.d.ts +3 -0
  54. package/dist/src/components/Stack/Stack.d.ts +15 -0
  55. package/dist/src/components/Stepper/Stepper.d.ts +3 -0
  56. package/dist/src/components/Switch/Switch.d.ts +13 -0
  57. package/dist/src/components/Switch/SwitchGroup.d.ts +9 -0
  58. package/dist/src/components/Table/Table.d.ts +3 -0
  59. package/dist/src/components/Tabs/Tabs.d.ts +3 -0
  60. package/dist/src/components/Text/Text.d.ts +17 -0
  61. package/dist/src/components/TextArea/TextArea.d.ts +15 -0
  62. package/dist/src/components/TextField/TextField.d.ts +9 -0
  63. package/dist/src/components/TimePicker/TimePicker.d.ts +3 -0
  64. package/dist/src/components/Timeline/Timeline.d.ts +3 -0
  65. package/dist/src/components/Title/Title.d.ts +13 -0
  66. package/dist/src/components/Toast/Toast.d.ts +3 -0
  67. package/dist/src/components/Tooltip/Tooltip.d.ts +3 -0
  68. package/dist/src/components/TransferList/TransferList.d.ts +3 -0
  69. package/dist/src/components/index.d.ts +48 -0
  70. package/dist/src/index.d.ts +2 -0
  71. package/dist/src/types/index.d.ts +6 -0
  72. package/dist/src/utils/ColorSchemeWrapper.d.ts +3 -0
  73. package/dist/src/utils/RequireAccessibleLabel.d.ts +18 -0
  74. package/dist/src/utils/copyToClipboard.d.ts +8 -0
  75. package/dist/src/utils/filterStylingProps.d.ts +36 -0
  76. package/dist/src/utils/index.d.ts +1 -0
  77. package/dist/vite.config.d.ts +2 -0
  78. package/dist/vite.svg +1 -0
  79. package/dist/vitest.workspace.d.ts +2 -0
  80. package/package.json +74 -35
  81. package/src/OverStyling.stories.tsx +174 -0
  82. package/src/Version.stories.tsx +56 -0
  83. package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +48 -0
  84. package/src/components/Accordion/Accordion.module.css +282 -0
  85. package/src/components/Accordion/Accordion.stories.tsx +145 -0
  86. package/src/components/Accordion/Accordion.tsx +200 -0
  87. package/src/components/Accordion/index.ts +1 -0
  88. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
  89. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +75 -0
  90. package/src/components/AssistiveElement/AssistiveElement.tsx +91 -0
  91. package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +24 -0
  92. package/src/components/Avatar/Avatar.module.css +340 -0
  93. package/src/components/Avatar/Avatar.stories.tsx +107 -0
  94. package/src/components/Avatar/Avatar.tsx +100 -0
  95. package/src/components/Avatar/index.ts +1 -0
  96. package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
  97. package/src/components/Badge/Badge.module.css +124 -0
  98. package/src/components/Badge/Badge.stories.tsx +78 -0
  99. package/src/components/Badge/Badge.tsx +66 -0
  100. package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +14 -0
  101. package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
  102. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +77 -0
  103. package/src/components/Breadcrumb/Breadcrumb.tsx +64 -0
  104. package/src/components/Button/Button.module.css +275 -0
  105. package/src/components/Button/Button.stories.tsx +103 -0
  106. package/src/components/Button/Button.tsx +122 -0
  107. package/src/components/Button/IMPLEMENTATION_NOTES.md +45 -0
  108. package/src/components/Button/index.ts +1 -0
  109. package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +10 -0
  110. package/src/components/Card/Card.module.css +60 -0
  111. package/src/components/Card/Card.stories.tsx +141 -0
  112. package/src/components/Card/Card.tsx +176 -0
  113. package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
  114. package/src/components/Checkbox/Checkbox.module.css +204 -0
  115. package/src/components/Checkbox/Checkbox.stories.tsx +94 -0
  116. package/src/components/Checkbox/Checkbox.tsx +159 -0
  117. package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
  118. package/src/components/Checkbox/CheckboxGroup.tsx +120 -0
  119. package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +35 -0
  120. package/src/components/Chip/Chip.module.css +218 -0
  121. package/src/components/Chip/Chip.stories.tsx +115 -0
  122. package/src/components/Chip/Chip.tsx +143 -0
  123. package/src/components/Container/CONTAINER_IMPLEMENTATION_NOTES.md +4 -0
  124. package/src/components/Container/Container.module.css +7 -0
  125. package/src/components/Container/Container.stories.tsx +118 -0
  126. package/src/components/Container/Container.tsx +89 -0
  127. package/src/components/DatePicker/DatePicker.stories.tsx +18 -0
  128. package/src/components/DatePicker/DatePicker.tsx +7 -0
  129. package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +7 -0
  130. package/src/components/Dropdown/Dropdown.module.css +272 -0
  131. package/src/components/Dropdown/Dropdown.stories.tsx +91 -0
  132. package/src/components/Dropdown/Dropdown.tsx +174 -0
  133. package/src/components/FileInput/FileInput.stories.tsx +18 -0
  134. package/src/components/FileInput/FileInput.tsx +7 -0
  135. package/src/components/FileUpload/FileUpload.stories.tsx +18 -0
  136. package/src/components/FileUpload/FileUpload.tsx +7 -0
  137. package/src/components/Flex/FLEX_IMPLEMENTATION_NOTES.md +4 -0
  138. package/src/components/Flex/Flex.module.css +7 -0
  139. package/src/components/Flex/Flex.stories.tsx +128 -0
  140. package/src/components/Flex/Flex.tsx +68 -0
  141. package/src/components/FormControlLayout/FormControlLayout.module.css +80 -0
  142. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +82 -0
  143. package/src/components/FormControlLayout/FormControlLayout.tsx +78 -0
  144. package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
  145. package/src/components/FormControlWrapper/FormControlWrapper.module.css +8 -0
  146. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +129 -0
  147. package/src/components/FormControlWrapper/FormControlWrapper.tsx +157 -0
  148. package/src/components/Group/GROUP_IMPLEMENTATION_NOTES.md +4 -0
  149. package/src/components/Group/Group.module.css +7 -0
  150. package/src/components/Group/Group.stories.tsx +120 -0
  151. package/src/components/Group/Group.tsx +68 -0
  152. package/src/components/HoverCard/HoverCard.stories.tsx +17 -0
  153. package/src/components/HoverCard/HoverCard.tsx +7 -0
  154. package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
  155. package/src/components/Label/Label.module.css +140 -0
  156. package/src/components/Label/Label.stories.tsx +122 -0
  157. package/src/components/Label/Label.tsx +127 -0
  158. package/src/components/Label/index.ts +1 -0
  159. package/src/components/Link/Link.stories.tsx +17 -0
  160. package/src/components/Link/Link.tsx +7 -0
  161. package/src/components/Loader/Loader.module.css +60 -0
  162. package/src/components/Loader/Loader.stories.tsx +103 -0
  163. package/src/components/Loader/Loader.tsx +76 -0
  164. package/src/components/Menu/Menu.stories.tsx +17 -0
  165. package/src/components/Menu/Menu.tsx +7 -0
  166. package/src/components/Modal/Modal.stories.tsx +17 -0
  167. package/src/components/Modal/Modal.tsx +7 -0
  168. package/src/components/NumberInput/NumberInput.stories.tsx +18 -0
  169. package/src/components/NumberInput/NumberInput.tsx +7 -0
  170. package/src/components/Pagination/Pagination.stories.tsx +17 -0
  171. package/src/components/Pagination/Pagination.tsx +7 -0
  172. package/src/components/Panel/Panel.stories.tsx +17 -0
  173. package/src/components/Panel/Panel.tsx +7 -0
  174. package/src/components/Popover/Popover.stories.tsx +17 -0
  175. package/src/components/Popover/Popover.tsx +7 -0
  176. package/src/components/Radio/Radio.module.css +207 -0
  177. package/src/components/Radio/Radio.stories.tsx +90 -0
  178. package/src/components/Radio/Radio.tsx +174 -0
  179. package/src/components/Radio/RadioGroup.stories.tsx +117 -0
  180. package/src/components/Radio/RadioGroup.tsx +118 -0
  181. package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
  182. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  183. package/src/components/ReadOnlyField/ReadOnlyField.module.css +49 -0
  184. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +163 -0
  185. package/src/components/ReadOnlyField/ReadOnlyField.tsx +102 -0
  186. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  187. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  188. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  189. package/src/components/ReadOnlyField/index.ts +5 -0
  190. package/src/components/Search/Search.stories.tsx +17 -0
  191. package/src/components/Search/Search.tsx +7 -0
  192. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +18 -0
  193. package/src/components/SegmentedControl/SegmentedControl.tsx +7 -0
  194. package/src/components/Slider/Slider.stories.tsx +18 -0
  195. package/src/components/Slider/Slider.tsx +7 -0
  196. package/src/components/Stack/STACK_IMPLEMENTATION_NOTES.md +4 -0
  197. package/src/components/Stack/Stack.module.css +7 -0
  198. package/src/components/Stack/Stack.stories.tsx +108 -0
  199. package/src/components/Stack/Stack.tsx +66 -0
  200. package/src/components/Stepper/Stepper.stories.tsx +17 -0
  201. package/src/components/Stepper/Stepper.tsx +7 -0
  202. package/src/components/Switch/SWITCH_IMPLEMENTATION_NOTES.md +28 -0
  203. package/src/components/Switch/Switch.module.css +199 -0
  204. package/src/components/Switch/Switch.stories.tsx +111 -0
  205. package/src/components/Switch/Switch.tsx +168 -0
  206. package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
  207. package/src/components/Switch/SwitchGroup.tsx +118 -0
  208. package/src/components/Table/Table.stories.tsx +17 -0
  209. package/src/components/Table/Table.tsx +7 -0
  210. package/src/components/Tabs/Tabs.stories.tsx +17 -0
  211. package/src/components/Tabs/Tabs.tsx +7 -0
  212. package/src/components/Text/Text.stories.tsx +88 -0
  213. package/src/components/Text/Text.tsx +54 -0
  214. package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +7 -0
  215. package/src/components/TextArea/TextArea.module.css +225 -0
  216. package/src/components/TextArea/TextArea.stories.tsx +91 -0
  217. package/src/components/TextArea/TextArea.tsx +152 -0
  218. package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
  219. package/src/components/TextField/TextField.module.css +225 -0
  220. package/src/components/TextField/TextField.stories.tsx +162 -0
  221. package/src/components/TextField/TextField.tsx +139 -0
  222. package/src/components/TimePicker/TimePicker.stories.tsx +18 -0
  223. package/src/components/TimePicker/TimePicker.tsx +7 -0
  224. package/src/components/Timeline/Timeline.stories.tsx +17 -0
  225. package/src/components/Timeline/Timeline.tsx +7 -0
  226. package/src/components/Title/Title.stories.tsx +63 -0
  227. package/src/components/Title/Title.tsx +45 -0
  228. package/src/components/Toast/Toast.stories.tsx +17 -0
  229. package/src/components/Toast/Toast.tsx +7 -0
  230. package/src/components/Tooltip/Tooltip.stories.tsx +17 -0
  231. package/src/components/Tooltip/Tooltip.tsx +7 -0
  232. package/src/components/TransferList/TransferList.stories.tsx +17 -0
  233. package/src/components/TransferList/TransferList.tsx +7 -0
  234. package/src/components/index.ts +48 -0
  235. package/src/env.d.ts +7 -0
  236. package/src/index.ts +3 -0
  237. package/src/types/index.ts +9 -0
  238. package/src/types/mantine.d.ts +7 -0
  239. package/src/types/scss-modules.d.ts +9 -0
  240. package/src/utils/ColorSchemeWrapper.tsx +27 -0
  241. package/src/utils/RequireAccessibleLabel.ts +12 -0
  242. package/src/utils/copyToClipboard.ts +36 -0
  243. package/src/utils/filterStylingProps.ts +141 -0
  244. package/src/utils/index.ts +1 -0
  245. package/dist/adapter/generateBorderRadiusType.d.ts +0 -3
  246. package/dist/adapter/generateBorderRadiusType.d.ts.map +0 -1
  247. package/dist/adapter/generateColorTypes.d.ts +0 -6
  248. package/dist/adapter/generateColorTypes.d.ts.map +0 -1
  249. package/dist/adapter/generateIcons.d.ts +0 -8
  250. package/dist/adapter/generateIcons.d.ts.map +0 -1
  251. package/dist/adapter/generateMantineTheme.d.ts +0 -19
  252. package/dist/adapter/generateMantineTheme.d.ts.map +0 -1
  253. package/dist/adapter/generatePrettierignore.d.ts +0 -3
  254. package/dist/adapter/generatePrettierignore.d.ts.map +0 -1
  255. package/dist/adapter/generateRecursicaObject.d.ts +0 -7
  256. package/dist/adapter/generateRecursicaObject.d.ts.map +0 -1
  257. package/dist/adapter/generateRecursicaThemes.d.ts +0 -12
  258. package/dist/adapter/generateRecursicaThemes.d.ts.map +0 -1
  259. package/dist/adapter/generateRecursicaTokens.d.ts +0 -3
  260. package/dist/adapter/generateRecursicaTokens.d.ts.map +0 -1
  261. package/dist/adapter/generateSpacersType.d.ts +0 -3
  262. package/dist/adapter/generateSpacersType.d.ts.map +0 -1
  263. package/dist/adapter/generateUiKit.d.ts +0 -8
  264. package/dist/adapter/generateUiKit.d.ts.map +0 -1
  265. package/dist/adapter/generateVanillaExtractThemes.d.ts +0 -12
  266. package/dist/adapter/generateVanillaExtractThemes.d.ts.map +0 -1
  267. package/dist/adapter/index.d.ts +0 -44
  268. package/dist/adapter/index.d.ts.map +0 -1
  269. package/dist/cli.d.ts +0 -6
  270. package/dist/cli.d.ts.map +0 -1
  271. package/dist/index.d.ts.map +0 -1
  272. package/dist/index.js +0 -921
  273. package/dist/index.js.map +0 -1
  274. package/dist/main.cjs +0 -928
  275. package/dist/main.cjs.map +0 -1
  276. package/dist/main.d.ts +0 -2
  277. package/dist/main.d.ts.map +0 -1
  278. package/dist/main.js +0 -926
  279. package/dist/main.js.map +0 -1
  280. package/dist/shared/processTokens.d.ts +0 -22
  281. package/dist/shared/processTokens.d.ts.map +0 -1
  282. package/dist/types.d.ts +0 -62
  283. package/dist/types.d.ts.map +0 -1
  284. package/dist/utils/fileCheck.d.ts +0 -8
  285. package/dist/utils/fileCheck.d.ts.map +0 -1
  286. package/dist/utils/loadConfig.d.ts +0 -24
  287. package/dist/utils/loadConfig.d.ts.map +0 -1
  288. package/dist/webworker.d.ts +0 -2
  289. package/dist/webworker.d.ts.map +0 -1
  290. package/dist/webworker.js +0 -791
@@ -0,0 +1,157 @@
1
+ import React, { forwardRef, useId } from "react";
2
+ import { type InputWrapperProps } from "@mantine/core";
3
+ import {
4
+ filterStylingProps,
5
+ type RecursicaOverStyled,
6
+ } from "../../utils/filterStylingProps";
7
+ import { Label, type RecursicaLabelProps } from "../Label/Label";
8
+ import { FormControlLayout } from "../FormControlLayout/FormControlLayout";
9
+ import { AssistiveElement } from "../AssistiveElement/AssistiveElement";
10
+ import styles from "./FormControlWrapper.module.css";
11
+
12
+ export interface RecursicaFormControlWrapperProps extends RecursicaLabelProps {
13
+ /** Overall structural flow mapping the Form Control natively cascading down to Label and Input logic. */
14
+ formLayout?: "stacked" | "side-by-side";
15
+ /** Securely replaces standard Mantine descriptions safely providing standard Assistive properties. */
16
+ assistiveText?: React.ReactNode;
17
+ /** Explicit toggle to suppress the Info icon rendering natively alongside the assistiveText. Defaults to true. */
18
+ assistiveWithIcon?: boolean;
19
+ /** Custom action area to render alongside the label instead of the default edit icon. */
20
+ labelActionArea?: React.ReactNode;
21
+ /** Pass the native maximum width design variable dynamically bounding the specific wrapper width exclusively. */
22
+ controlMaxWidth: string | undefined;
23
+ /** Pass the native minimum width design variable dynamically bounding the specific wrapper width exclusively. */
24
+ controlMinWidth: string | undefined;
25
+ }
26
+
27
+ export type FormControlWrapperProps = RecursicaOverStyled<
28
+ Omit<InputWrapperProps, "labelProps" | "inputWrapperOrder"> &
29
+ RecursicaFormControlWrapperProps
30
+ >;
31
+
32
+ export const FormControlWrapper = forwardRef<
33
+ HTMLDivElement,
34
+ FormControlWrapperProps
35
+ >(function FormControlWrapper(
36
+ {
37
+ formLayout,
38
+ labelSize,
39
+ labelAlignment,
40
+ labelOptionalText,
41
+ labelWithEditIcon,
42
+ labelActionArea,
43
+ onLabelEditClick,
44
+
45
+ label,
46
+ description,
47
+ assistiveText,
48
+ assistiveWithIcon = true,
49
+ controlMaxWidth,
50
+ controlMinWidth,
51
+ error,
52
+ required,
53
+ withAsterisk,
54
+ id: userProvidedId,
55
+ children,
56
+ className,
57
+ overStyled = false,
58
+ labelElement, // Extracted safely preventing bleeding into HTML domains
59
+ ...rest
60
+ },
61
+ ref,
62
+ ) {
63
+ // Generate a reliable ID to map the Label's HTML context down to the component array natively.
64
+ const generatedId = useId();
65
+ const id = userProvidedId || `recursica-fc-${generatedId}`;
66
+
67
+ // Evaluate explicit assistive fallbacks ensuring assistiveText correctly prioritizes natively over underlying Mantine configurations!
68
+ const resolvedAssistive = assistiveText || description;
69
+ const assistiveId = resolvedAssistive ? `${id}-assistive` : undefined;
70
+ const errorId = error ? `${id}-error` : undefined;
71
+
72
+ const sanitizedProps = filterStylingProps(rest, overStyled);
73
+ const restRecord = sanitizedProps as Record<string, unknown>;
74
+
75
+ const classNameProp =
76
+ className || (restRecord.className as string | undefined);
77
+ const rootClass = styles.root;
78
+ const finalClass = classNameProp
79
+ ? `${rootClass} ${classNameProp}`
80
+ : rootClass;
81
+
82
+ // Clone ARIA identifiers directly back down into the nested children wrapper so screen-readers natively hook the external strings
83
+ const content = React.isValidElement(children)
84
+ ? React.cloneElement(
85
+ children as React.ReactElement<Record<string, unknown>>,
86
+ {
87
+ ...(resolvedAssistive &&
88
+ !(children.props as Record<string, unknown>)["aria-describedby"]
89
+ ? { "aria-describedby": assistiveId }
90
+ : {}),
91
+ ...(error &&
92
+ !(children.props as Record<string, unknown>)["aria-errormessage"]
93
+ ? { "aria-errormessage": errorId }
94
+ : {}),
95
+ },
96
+ )
97
+ : children;
98
+
99
+ const labelNode = label ? (
100
+ <Label
101
+ id={id} // Directly binds ARIA references down
102
+ labelAlignment={labelAlignment}
103
+ labelOptionalText={labelOptionalText}
104
+ labelWithEditIcon={labelWithEditIcon}
105
+ labelActionArea={labelActionArea}
106
+ onLabelEditClick={onLabelEditClick}
107
+ required={withAsterisk ?? required}
108
+ // Manually propagate relevant structural logic if underlying groups dictate Label to act as generic wrapper
109
+ {...(labelElement === "div" ? { as: "div" } : {})}
110
+ >
111
+ {label}
112
+ </Label>
113
+ ) : undefined;
114
+
115
+ return (
116
+ <FormControlLayout
117
+ ref={ref}
118
+ className={finalClass}
119
+ formLayout={formLayout}
120
+ labelSize={labelSize}
121
+ controlMaxWidth={controlMaxWidth}
122
+ controlMinWidth={controlMinWidth}
123
+ leftSection={labelNode}
124
+ {...restRecord}
125
+ >
126
+ {/*
127
+ The Core Input Wrapper & Controls
128
+ Nakedly inject the actual field elements alongside natively bridged Assistive components mapped dynamically.
129
+ */}
130
+ <div className={styles.inputSection}>
131
+ {content}
132
+
133
+ {error && (
134
+ <AssistiveElement
135
+ id={errorId}
136
+ assistiveVariant="error"
137
+ assistiveWithIcon={assistiveWithIcon}
138
+ >
139
+ {error}
140
+ </AssistiveElement>
141
+ )}
142
+
143
+ {!error && resolvedAssistive && (
144
+ <AssistiveElement
145
+ id={assistiveId}
146
+ assistiveVariant="help"
147
+ assistiveWithIcon={assistiveWithIcon}
148
+ >
149
+ {resolvedAssistive}
150
+ </AssistiveElement>
151
+ )}
152
+ </div>
153
+ </FormControlLayout>
154
+ );
155
+ });
156
+
157
+ FormControlWrapper.displayName = "FormControlWrapper";
@@ -0,0 +1,4 @@
1
+ # Group Implementation Notes
2
+
3
+ The `Group` component is a generic flex layout wrapper mapped directly to Mantine's `Group`.
4
+ It currently does not require any custom logical layouts or CSS workarounds since it serves only to organize layout structure, and doesn't enforce any strict design-system token styling itself. All gap, align, wrap, and justify properties pass safely through via the `filterStylingProps` layout-property allowance.
@@ -0,0 +1,7 @@
1
+ /* HARDCODED VALUES:
2
+ * None. This is a generic flex layout wrapper.
3
+ */
4
+
5
+ .root {
6
+ /* Mantine handles flex, gap, align, justify. No intrinsic design-system styles required for pure layout wrappers. */
7
+ }
@@ -0,0 +1,120 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { Group } from "./Group";
4
+ import { Button } from "../Button";
5
+ import { Text } from "../Text/Text";
6
+
7
+ type GroupStoryProps = React.ComponentProps<typeof Group>;
8
+
9
+ const meta: Meta<GroupStoryProps> = {
10
+ title: "UI-Kit/Group",
11
+ component: Group,
12
+ tags: ["autodocs"],
13
+ parameters: {
14
+ docs: {
15
+ description: {
16
+ component:
17
+ "Group is a flex horizontal layout container that maps directly to Mantine's Group component allowing safe layout property passing.",
18
+ },
19
+ },
20
+ },
21
+ args: {
22
+ gap: "rec-default",
23
+ align: "center",
24
+ justify: "flex-start",
25
+ wrap: "wrap",
26
+ },
27
+ argTypes: {
28
+ gap: {
29
+ control: "select",
30
+ options: [
31
+ "rec-none",
32
+ "rec-sm",
33
+ "rec-default",
34
+ "rec-md",
35
+ "rec-lg",
36
+ "rec-xl",
37
+ "rec-2xl",
38
+ "xs",
39
+ "sm",
40
+ "md",
41
+ "lg",
42
+ "xl",
43
+ ],
44
+ description: "Gap between elements",
45
+ },
46
+ align: {
47
+ control: "select",
48
+ options: ["flex-start", "center", "flex-end", "stretch"],
49
+ description: "Align-items property",
50
+ },
51
+ justify: {
52
+ control: "select",
53
+ options: [
54
+ "flex-start",
55
+ "center",
56
+ "flex-end",
57
+ "space-between",
58
+ "space-around",
59
+ ],
60
+ description: "Justify-content property",
61
+ },
62
+ wrap: {
63
+ control: "select",
64
+ options: ["wrap", "nowrap", "wrap-reverse"],
65
+ description: "Flex-wrap property",
66
+ },
67
+ defaultChecked: {
68
+ table: { disable: true },
69
+ },
70
+ rowGap: {
71
+ table: { disable: true },
72
+ },
73
+ columnGap: {
74
+ table: { disable: true },
75
+ },
76
+ },
77
+ };
78
+
79
+ export default meta;
80
+
81
+ type Story = StoryObj<GroupStoryProps>;
82
+
83
+ export const Default: Story = {
84
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
85
+ render: ({ withLayer, layer, ...args }: any) => (
86
+ <Group {...args}>
87
+ <Button variant="solid">Primary</Button>
88
+ <Button variant="outline">Secondary</Button>
89
+ <Text>Text element within Group</Text>
90
+ </Group>
91
+ ),
92
+ };
93
+
94
+ export const StaticGapSmall: Story = {
95
+ args: {
96
+ gap: "rec-sm",
97
+ },
98
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
99
+ render: ({ withLayer, layer, ...args }: any) => (
100
+ <Group {...args}>
101
+ <Button variant="solid">Item 1</Button>
102
+ <Button variant="solid">Item 2</Button>
103
+ <Button variant="solid">Item 3</Button>
104
+ </Group>
105
+ ),
106
+ };
107
+
108
+ export const StaticGapLarge: Story = {
109
+ args: {
110
+ gap: "rec-xl",
111
+ },
112
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
113
+ render: ({ withLayer, layer, ...args }: any) => (
114
+ <Group {...args}>
115
+ <Button variant="solid">Item 1</Button>
116
+ <Button variant="solid">Item 2</Button>
117
+ <Button variant="solid">Item 3</Button>
118
+ </Group>
119
+ ),
120
+ };
@@ -0,0 +1,68 @@
1
+ import React, { forwardRef } from "react";
2
+ import {
3
+ Group as MantineGroup,
4
+ type GroupProps as MantineGroupProps,
5
+ } from "@mantine/core";
6
+ import {
7
+ filterStylingProps,
8
+ type RecursicaOverStyled,
9
+ type RecursicaSpacing,
10
+ } from "../../utils/filterStylingProps";
11
+ import styles from "./Group.module.css";
12
+
13
+ export interface RecursicaGroupProps {
14
+ /**
15
+ * Children components inside the group
16
+ */
17
+ children?: React.ReactNode;
18
+ gap?: MantineGroupProps["gap"] | RecursicaSpacing;
19
+ rowGap?: MantineGroupProps["gap"] | RecursicaSpacing;
20
+ columnGap?: MantineGroupProps["gap"] | RecursicaSpacing;
21
+ }
22
+
23
+ /**
24
+ * Group flex layout wrapper
25
+ */
26
+ export type GroupProps = RecursicaOverStyled<
27
+ MantineGroupProps & RecursicaGroupProps
28
+ >;
29
+
30
+ export const Group = forwardRef<HTMLDivElement, GroupProps>(function Group(
31
+ { children, overStyled = false, gap = "rec-default", ...rest },
32
+ ref,
33
+ ) {
34
+ const sanitizedProps = filterStylingProps({ ...rest, gap }, overStyled);
35
+ const restRecord = sanitizedProps as Record<string, unknown>;
36
+
37
+ const mergedClassNames: Partial<Record<string, string>> = {
38
+ root: styles.root,
39
+ };
40
+
41
+ const classNamesProp = restRecord.classNames;
42
+ if (
43
+ classNamesProp &&
44
+ typeof classNamesProp === "object" &&
45
+ !Array.isArray(classNamesProp)
46
+ ) {
47
+ const o = classNamesProp as Partial<Record<string, string>>;
48
+ mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
49
+ }
50
+
51
+ const classNameProp = restRecord.className as string | undefined;
52
+ const finalClass = classNameProp
53
+ ? `${styles.root} ${classNameProp}`
54
+ : styles.root;
55
+
56
+ return (
57
+ <MantineGroup
58
+ ref={ref}
59
+ className={finalClass}
60
+ classNames={mergedClassNames}
61
+ {...sanitizedProps}
62
+ >
63
+ {children}
64
+ </MantineGroup>
65
+ );
66
+ });
67
+
68
+ Group.displayName = "Group";
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { HoverCard } from "./HoverCard";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof HoverCard> = {
6
+ title: "UI-Kit/🚧 HoverCard",
7
+ component: HoverCard,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof HoverCard>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="HoverCard" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type HoverCardProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const HoverCard: React.FC<HoverCardProps> = (props) => {
6
+ return <div {...props}>HoverCard</div>;
7
+ };
@@ -0,0 +1,48 @@
1
+ # Label Implementation Notes
2
+
3
+ ## Architecture Overview
4
+
5
+ The `Label` component is fundamentally built as a strict, localized wrapper around Mantine's native `Input.Label`. The core goal is to preserve context, ref-forwarding, and native accessibility links, while completely overriding visual behaviors via Recursica design variables in scoped CSS.
6
+
7
+ ## Key Design Decisions
8
+
9
+ ### **Layout Architecture**
10
+
11
+ - Because Recursica dictates complex alignments between primary label text, asterisks, edit icons, and optional strings, Mantine's rigid form label flow could not be used out-of-the-box.
12
+ - Implemented `display: flex; flex-wrap: wrap;` directly on `.root`.
13
+ - Injected strict integer-based flex `order` properties (e.g. `order: 1` for text, `order: 2` for `required`, `order: 5` for `optionalText`) to physically decouple DOM rendering from markup flow.
14
+ - Because `optionalText` often acts as secondary contextual detail, it forces `flex-basis: 100%`, securely wrapping to a secondary line underneath the primary label properties and transforming the horizontal gap spacing seamlessly into a `margin-top` vector.
15
+
16
+ ### **Optional Text & Required Mutually Exclusive Parsing**
17
+
18
+ - By design standards, a component cannot logically be both "Required" and mapped as "Optional".
19
+ - To bulletproof implementations natively, the adapter forcibly suppresses rendering of the `resolvedOptionalText` strings if the parent wrapper invokes `required={true}`.
20
+ - `optionalText` can operate as dynamic data or specifically as a boolean `true`, which forces the adapter to natively render the formal `(Optional)` string map.
21
+
22
+ ### **The "Edit Icon" Replacer Logic**
23
+
24
+ - Passing `withEditIcon={true}` evaluates it as fundamentally mutually exclusive to the standard required indicator asterisk.
25
+ - `required={required && !withEditIcon}` is passed to the underlying Mantine structure so the native `*` is entirely suppressed.
26
+ - Added localized styling via `data-replaces-asterisk={required ? "true" : undefined}` onto the `.editIconWrapper` element. If an editable instance is simultaneously designated as required, the edit icon functionally assumes the indicator role natively, overriding its default icon metrics explicitly to match `--recursica_ui-kit_components_label_properties_colors_asterisk`.
27
+
28
+ ### **Bypassing `Input.Wrapper` Integrations**
29
+
30
+ - By decoupling from Mantine's standard `Input.Wrapper`, the `Label` component is exclusively mapped manually through `FormControlWrapper`. This grants us exact visual sync regarding where the label renders based on `formLayout="stacked"` or `formLayout="side-by-side"`, without fighting internal Mantine positional hooks that assume vertical stacking by default.
31
+
32
+ ### **Label Size Container Constraints**
33
+
34
+ - The `labelSize` parameter (mapping values like `"small"`) internally **does not scale typographic font metrics**. Instead, it dynamically defines the explicit horizontal bounding width limit of the block container itself.
35
+ - **Architectural Rule:** `labelSize` modifications are strictly designed to execute exclusively when `formLayout="side-by-side"` is active. It acts as an optical grid threshold ensuring left-aligned string wrappers constrain correctly uniformly down a column without bleeding into the physical input arrays alongside them.
36
+
37
+ ## Outstanding Technical Debt / Issues
38
+
39
+ ### **Description Property Omission**
40
+
41
+ - **Issue:** Currently, the adapter `Label` does not natively parse or support a structured `description` node directly attached beneath it.
42
+ - **Context:** Standard forms often attach subtext beneath inputs, but mapping a description purely within the `<Label>` (distinct from an overall form-control description) is omitted structurally until subsequent UI Kit requirements mandate dedicated `description` styles locally on the label component itself.
43
+
44
+ ### **Global Interactive Hover Mappings**
45
+
46
+ - **Issue:** Currently, the `editIconWrapper` lacks a dedicated hover background layer.
47
+ - **Context:** While the global theme abstracts interactive hover environments deeply using layered variable syntax (e.g., `--recursica_brand_layer_1_elements_interactive_hover-color`), Recursica's token generation framework natively fails to expose a universally generic placeholder token (e.g., `--recursica_elements_interactive_hover-color`) which downstream wrappers can map their `<Layer>` injections directly into safely.
48
+ - **Resolution Path:** We are explicitly ignoring the `.editIconWrapper:hover` background color assignment until the raw Figma token exports directly scaffold a generic token placeholder that we can interface cleanly with across arbitrary `<Layer>` contexts, avoiding manually mapping statically hardcoded depths (`layer-0`, `layer-1`).
@@ -0,0 +1,140 @@
1
+ /* HARDCODED VALUES:
2
+ - display: flex helps us leverage flex 'order' to perfectly position Mantine's injected asterisk.
3
+ - align-items: baseline ensures text logic lines up nicely if font sizes differ slightly.
4
+ - margin/padding resets.
5
+ */
6
+
7
+ .root {
8
+ display: flex;
9
+ flex-wrap: wrap;
10
+ align-items: baseline;
11
+ box-sizing: border-box;
12
+ margin: 0;
13
+ color: var(--recursica_ui-kit_components_label_properties_colors_text);
14
+ }
15
+
16
+ .root[data-alignment="left"] {
17
+ justify-content: flex-start;
18
+ text-align: left;
19
+ }
20
+
21
+ .root[data-alignment="right"] {
22
+ justify-content: flex-end;
23
+ text-align: right;
24
+ }
25
+
26
+ .labelText {
27
+ order: 1;
28
+ font-family: var(
29
+ --recursica_ui-kit_components_label_properties_label-text_font-family
30
+ );
31
+ font-size: var(
32
+ --recursica_ui-kit_components_label_properties_label-text_font-size
33
+ );
34
+ font-weight: var(
35
+ --recursica_ui-kit_components_label_properties_label-text_font-weight
36
+ );
37
+ letter-spacing: var(
38
+ --recursica_ui-kit_components_label_properties_label-text_letter-spacing
39
+ );
40
+ line-height: var(
41
+ --recursica_ui-kit_components_label_properties_label-text_line-height
42
+ );
43
+ font-style: var(
44
+ --recursica_ui-kit_components_label_properties_label-text_font-style,
45
+ normal
46
+ );
47
+ text-decoration: var(
48
+ --recursica_ui-kit_components_label_properties_label-text_text-decoration,
49
+ none
50
+ );
51
+ text-transform: var(
52
+ --recursica_ui-kit_components_label_properties_label-text_text-transform,
53
+ none
54
+ );
55
+ }
56
+
57
+ .required {
58
+ order: 2;
59
+ margin-left: var(
60
+ --recursica_ui-kit_components_label_properties_required-indicator-gap
61
+ );
62
+ color: var(--recursica_ui-kit_components_label_properties_colors_asterisk);
63
+
64
+ /* Inherit identical typography bounds to prevent flex row line-height stretching */
65
+ font-family: var(
66
+ --recursica_ui-kit_components_label_properties_label-text_font-family
67
+ );
68
+ font-size: var(
69
+ --recursica_ui-kit_components_label_properties_label-text_font-size
70
+ );
71
+ line-height: var(
72
+ --recursica_ui-kit_components_label_properties_label-text_line-height
73
+ );
74
+ }
75
+
76
+ .optionalText {
77
+ order: 5;
78
+ flex-basis: 100%;
79
+ margin-top: var(
80
+ --recursica_ui-kit_components_label_properties_label-optional-text-gap
81
+ );
82
+ margin-left: 0;
83
+ font-family: var(
84
+ --recursica_ui-kit_components_label_properties_optional-text_font-family
85
+ );
86
+ font-size: var(
87
+ --recursica_ui-kit_components_label_properties_optional-text_font-size
88
+ );
89
+ font-weight: var(
90
+ --recursica_ui-kit_components_label_properties_optional-text_font-weight
91
+ );
92
+ letter-spacing: var(
93
+ --recursica_ui-kit_components_label_properties_optional-text_letter-spacing
94
+ );
95
+ line-height: var(
96
+ --recursica_ui-kit_components_label_properties_optional-text_line-height
97
+ );
98
+ font-style: normal;
99
+ text-decoration: var(
100
+ --recursica_ui-kit_components_label_properties_optional-text_text-decoration,
101
+ none
102
+ );
103
+ text-transform: var(
104
+ --recursica_ui-kit_components_label_properties_optional-text_text-transform,
105
+ none
106
+ );
107
+ color: inherit;
108
+ opacity: var(
109
+ --recursica_ui-kit_components_label_properties_colors_optional-text-opacity
110
+ );
111
+ }
112
+
113
+ .actionAreaWrapper {
114
+ order: 4;
115
+ margin-left: var(
116
+ --recursica_ui-kit_components_label_properties_edit-icon-gap
117
+ );
118
+ display: inline-flex;
119
+ align-items: center;
120
+ justify-content: center;
121
+ }
122
+
123
+ .editIconWrapper {
124
+ order: 4;
125
+ margin-left: var(
126
+ --recursica_ui-kit_components_label_properties_edit-icon-gap
127
+ );
128
+ background: none;
129
+ border: none;
130
+ padding: 0;
131
+ cursor: pointer;
132
+ display: inline-flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ color: inherit;
136
+ }
137
+
138
+ .editIconWrapper[data-replaces-asterisk="true"] {
139
+ color: var(--recursica_ui-kit_components_label_properties_colors_asterisk);
140
+ }