@recursica/mui-adapter 0.5.0 → 0.7.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 (212) hide show
  1. package/ARCHITECTURE.md +15 -0
  2. package/CHANGELOG.md +15 -0
  3. package/SETUP.md +77 -0
  4. package/USAGE.md +55 -0
  5. package/dist/mui-adapter.cjs +74 -1
  6. package/dist/mui-adapter.cjs.map +1 -1
  7. package/dist/mui-adapter.css +1 -1
  8. package/dist/mui-adapter.js +6863 -205
  9. package/dist/mui-adapter.js.map +1 -1
  10. package/dist/src/components/Accordion/Accordion.d.ts +43 -2
  11. package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +6 -2
  12. package/dist/src/components/Autocomplete/Autocomplete.d.ts +12 -2
  13. package/dist/src/components/Avatar/Avatar.d.ts +10 -3
  14. package/dist/src/components/Badge/Badge.d.ts +10 -3
  15. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +9 -3
  16. package/dist/src/components/Button/Button.d.ts +2 -17
  17. package/dist/src/components/Card/Card.d.ts +38 -3
  18. package/dist/src/components/Checkbox/Checkbox.d.ts +13 -2
  19. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +18 -0
  20. package/dist/src/components/Checkbox/index.d.ts +5 -1
  21. package/dist/src/components/Chip/Chip.d.ts +9 -2
  22. package/dist/src/components/Container/Container.d.ts +1 -5
  23. package/dist/src/components/DatePicker/DatePicker.d.ts +2 -1
  24. package/dist/src/components/Dropdown/Dropdown.d.ts +12 -2
  25. package/dist/src/components/Flex/Flex.d.ts +2 -22
  26. package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +5 -2
  27. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +9 -2
  28. package/dist/src/components/Group/Group.d.ts +2 -7
  29. package/dist/src/components/HoverCard/HoverCard.d.ts +28 -2
  30. package/dist/src/components/Label/Label.d.ts +6 -2
  31. package/dist/src/components/Link/Link.d.ts +2 -6
  32. package/dist/src/components/Loader/Loader.d.ts +2 -7
  33. package/dist/src/components/Menu/Menu.d.ts +25 -3
  34. package/dist/src/components/Modal/Modal.d.ts +37 -2
  35. package/dist/src/components/NumberInput/NumberInput.d.ts +12 -2
  36. package/dist/src/components/Pagination/Pagination.d.ts +12 -3
  37. package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
  38. package/dist/src/components/Panel/Panel.d.ts +52 -3
  39. package/dist/src/components/Radio/Radio.d.ts +13 -3
  40. package/dist/src/components/Radio/RadioGroup.d.ts +9 -0
  41. package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
  42. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +4 -2
  43. package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
  44. package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
  45. package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +28 -0
  46. package/dist/src/components/ReadOnlyField/index.d.ts +1 -0
  47. package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +21 -3
  48. package/dist/src/components/Slider/Slider.d.ts +18 -2
  49. package/dist/src/components/Stack/Stack.d.ts +2 -5
  50. package/dist/src/components/Stepper/Stepper.d.ts +41 -2
  51. package/dist/src/components/Switch/Switch.d.ts +10 -3
  52. package/dist/src/components/Switch/SwitchGroup.d.ts +13 -0
  53. package/dist/src/components/Table/Table.d.ts +2 -1
  54. package/dist/src/components/Tabs/Tabs.d.ts +20 -3
  55. package/dist/src/components/Text/Text.d.ts +2 -16
  56. package/dist/src/components/TextArea/TextArea.d.ts +12 -2
  57. package/dist/src/components/TextField/TextField.d.ts +12 -2
  58. package/dist/src/components/TimePicker/TimePicker.d.ts +2 -1
  59. package/dist/src/components/Timeline/Timeline.d.ts +15 -2
  60. package/dist/src/components/Timeline/TimelineItem.d.ts +18 -0
  61. package/dist/src/components/Title/Title.d.ts +2 -15
  62. package/dist/src/components/Toast/Toast.d.ts +20 -2
  63. package/dist/src/components/Tooltip/Tooltip.d.ts +28 -3
  64. package/dist/src/components/TransferList/TransferList.d.ts +2 -1
  65. package/dist/src/components/Typography/Typography.d.ts +1 -1
  66. package/dist/src/utils/RequireAccessibleLabel.d.ts +1 -18
  67. package/dist/src/utils/filterStylingProps.d.ts +1 -11
  68. package/llms.txt +16 -0
  69. package/package.json +14 -3
  70. package/src/components/Accordion/Accordion.module.css +294 -56
  71. package/src/components/Accordion/Accordion.stories.tsx +131 -21
  72. package/src/components/Accordion/Accordion.tsx +260 -5
  73. package/src/components/AssistiveElement/AssistiveElement.module.css +114 -20
  74. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +60 -20
  75. package/src/components/AssistiveElement/AssistiveElement.tsx +81 -5
  76. package/src/components/Autocomplete/Autocomplete.module.css +319 -42
  77. package/src/components/Autocomplete/Autocomplete.stories.tsx +175 -23
  78. package/src/components/Autocomplete/Autocomplete.tsx +181 -6
  79. package/src/components/Avatar/Avatar.module.css +343 -73
  80. package/src/components/Avatar/Avatar.stories.tsx +94 -22
  81. package/src/components/Avatar/Avatar.tsx +99 -6
  82. package/src/components/Badge/Badge.module.css +127 -29
  83. package/src/components/Badge/Badge.stories.tsx +65 -22
  84. package/src/components/Badge/Badge.tsx +67 -6
  85. package/src/components/Breadcrumb/Breadcrumb.module.css +25 -5
  86. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +57 -22
  87. package/src/components/Breadcrumb/Breadcrumb.tsx +59 -6
  88. package/src/components/Button/Button.module.css +19 -61
  89. package/src/components/Button/Button.stories.tsx +24 -23
  90. package/src/components/Button/Button.tsx +7 -18
  91. package/src/components/Card/Card.module.css +154 -38
  92. package/src/components/Card/Card.stories.tsx +117 -19
  93. package/src/components/Card/Card.tsx +181 -5
  94. package/src/components/Checkbox/Checkbox.module.css +249 -39
  95. package/src/components/Checkbox/Checkbox.stories.tsx +81 -19
  96. package/src/components/Checkbox/Checkbox.tsx +246 -5
  97. package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
  98. package/src/components/Checkbox/CheckboxGroup.tsx +137 -0
  99. package/src/components/Checkbox/index.ts +6 -1
  100. package/src/components/Chip/Chip.module.css +246 -43
  101. package/src/components/Chip/Chip.stories.tsx +101 -21
  102. package/src/components/Chip/Chip.tsx +136 -6
  103. package/src/components/Container/Container.stories.tsx +103 -20
  104. package/src/components/Container/Container.tsx +1 -13
  105. package/src/components/DatePicker/DatePicker.stories.tsx +125 -19
  106. package/src/components/DatePicker/DatePicker.tsx +3 -1
  107. package/src/components/Dropdown/Dropdown.module.css +291 -41
  108. package/src/components/Dropdown/Dropdown.stories.tsx +80 -21
  109. package/src/components/Dropdown/Dropdown.tsx +180 -6
  110. package/src/components/FileInput/FileInput.stories.tsx +2 -19
  111. package/src/components/FileUpload/FileUpload.stories.tsx +2 -19
  112. package/src/components/Flex/Flex.stories.tsx +113 -20
  113. package/src/components/Flex/Flex.tsx +16 -26
  114. package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
  115. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +67 -20
  116. package/src/components/FormControlLayout/FormControlLayout.tsx +69 -4
  117. package/src/components/FormControlWrapper/FormControlWrapper.module.css +87 -0
  118. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -22
  119. package/src/components/FormControlWrapper/FormControlWrapper.tsx +126 -6
  120. package/src/components/Group/Group.stories.tsx +6 -30
  121. package/src/components/Group/Group.tsx +14 -9
  122. package/src/components/HoverCard/HoverCard.module.css +90 -22
  123. package/src/components/HoverCard/HoverCard.stories.tsx +158 -21
  124. package/src/components/HoverCard/HoverCard.tsx +147 -5
  125. package/src/components/Label/Label.module.css +140 -35
  126. package/src/components/Label/Label.stories.tsx +108 -21
  127. package/src/components/Label/Label.tsx +82 -5
  128. package/src/components/Link/Link.module.css +4 -3
  129. package/src/components/Link/Link.stories.tsx +2 -8
  130. package/src/components/Link/Link.tsx +1 -5
  131. package/src/components/Loader/Loader.module.css +1 -2
  132. package/src/components/Loader/Loader.tsx +1 -7
  133. package/src/components/Menu/IMPLEMENTATION_NOTES.md +4 -0
  134. package/src/components/Menu/Menu.module.css +285 -51
  135. package/src/components/Menu/Menu.stories.tsx +229 -25
  136. package/src/components/Menu/Menu.tsx +73 -6
  137. package/src/components/Modal/Modal.module.css +171 -35
  138. package/src/components/Modal/Modal.stories.tsx +66 -22
  139. package/src/components/Modal/Modal.tsx +215 -5
  140. package/src/components/NumberInput/NumberInput.module.css +276 -42
  141. package/src/components/NumberInput/NumberInput.stories.tsx +83 -20
  142. package/src/components/NumberInput/NumberInput.tsx +136 -6
  143. package/src/components/Pagination/IMPLEMENTATION_NOTES.md +3 -0
  144. package/src/components/Pagination/Pagination.icons.tsx +66 -0
  145. package/src/components/Pagination/Pagination.module.css +234 -20
  146. package/src/components/Pagination/Pagination.stories.tsx +34 -21
  147. package/src/components/Pagination/Pagination.tsx +74 -6
  148. package/src/components/Panel/Panel.module.css +206 -38
  149. package/src/components/Panel/Panel.stories.tsx +214 -22
  150. package/src/components/Panel/Panel.tsx +130 -5
  151. package/src/components/Radio/Radio.module.css +235 -37
  152. package/src/components/Radio/Radio.stories.tsx +77 -19
  153. package/src/components/Radio/Radio.tsx +210 -5
  154. package/src/components/Radio/RadioGroup.stories.tsx +117 -0
  155. package/src/components/Radio/RadioGroup.tsx +125 -0
  156. package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
  157. package/src/components/ReadOnlyField/ReadOnlyField.module.css +53 -15
  158. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +147 -19
  159. package/src/components/ReadOnlyField/ReadOnlyField.tsx +105 -5
  160. package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
  161. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
  162. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
  163. package/src/components/ReadOnlyField/index.ts +1 -0
  164. package/src/components/SegmentedControl/SegmentedControl.module.css +179 -47
  165. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +102 -20
  166. package/src/components/SegmentedControl/SegmentedControl.tsx +140 -6
  167. package/src/components/Slider/Slider.module.css +539 -86
  168. package/src/components/Slider/Slider.stories.tsx +157 -19
  169. package/src/components/Slider/Slider.tsx +283 -5
  170. package/src/components/Stack/Stack.stories.tsx +4 -25
  171. package/src/components/Stack/Stack.tsx +1 -5
  172. package/src/components/Stepper/IMPLEMENTATION_NOTES.md +4 -0
  173. package/src/components/Stepper/Stepper.module.css +410 -71
  174. package/src/components/Stepper/Stepper.stories.tsx +146 -20
  175. package/src/components/Stepper/Stepper.tsx +147 -6
  176. package/src/components/Switch/Switch.module.css +259 -39
  177. package/src/components/Switch/Switch.stories.tsx +98 -19
  178. package/src/components/Switch/Switch.tsx +200 -6
  179. package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
  180. package/src/components/Switch/SwitchGroup.tsx +120 -0
  181. package/src/components/Table/Table.stories.tsx +1 -19
  182. package/src/components/Table/Table.tsx +3 -1
  183. package/src/components/Tabs/IMPLEMENTATION_NOTES.md +4 -0
  184. package/src/components/Tabs/Tabs.module.css +422 -79
  185. package/src/components/Tabs/Tabs.stories.tsx +156 -20
  186. package/src/components/Tabs/Tabs.tsx +86 -6
  187. package/src/components/Text/Text.stories.tsx +5 -17
  188. package/src/components/Text/Text.tsx +1 -15
  189. package/src/components/TextArea/TextArea.module.css +155 -32
  190. package/src/components/TextArea/TextArea.stories.tsx +80 -21
  191. package/src/components/TextArea/TextArea.tsx +146 -6
  192. package/src/components/TextField/TextField.module.css +261 -42
  193. package/src/components/TextField/TextField.stories.tsx +147 -20
  194. package/src/components/TextField/TextField.tsx +169 -6
  195. package/src/components/TimePicker/TimePicker.stories.tsx +2 -19
  196. package/src/components/TimePicker/TimePicker.tsx +3 -1
  197. package/src/components/Timeline/Timeline.module.css +365 -76
  198. package/src/components/Timeline/Timeline.stories.tsx +114 -21
  199. package/src/components/Timeline/Timeline.tsx +83 -5
  200. package/src/components/Timeline/TimelineItem.tsx +90 -0
  201. package/src/components/Title/Title.stories.tsx +0 -18
  202. package/src/components/Title/Title.tsx +1 -7
  203. package/src/components/Toast/Toast.module.css +166 -28
  204. package/src/components/Toast/Toast.stories.tsx +54 -22
  205. package/src/components/Toast/Toast.tsx +124 -5
  206. package/src/components/Tooltip/Tooltip.module.css +89 -24
  207. package/src/components/Tooltip/Tooltip.stories.tsx +152 -22
  208. package/src/components/Tooltip/Tooltip.tsx +88 -5
  209. package/src/components/TransferList/TransferList.stories.tsx +1 -19
  210. package/src/components/TransferList/TransferList.tsx +3 -1
  211. package/src/utils/RequireAccessibleLabel.ts +1 -12
  212. package/src/utils/filterStylingProps.ts +7 -20
@@ -1,35 +1,173 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
2
  import { Slider } from "./Slider";
3
- import { ComingSoon } from "@recursica/storybook-template";
3
+ import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
4
4
 
5
5
  const meta: Meta<typeof Slider> = {
6
- title: "UI-Kit/🚧 Slider",
6
+ title: "UI-Kit/Slider",
7
7
  component: Slider,
8
8
  tags: ["autodocs"],
9
9
  parameters: {
10
- controls: {
11
- include: [
12
- "layer",
13
- "withLayer",
14
- "children",
15
- "component",
16
- "variant",
17
- "size",
18
- "icon",
19
- "disabled",
20
- "href",
21
- "onClick",
22
- "onChange",
23
- "value",
24
- "checked",
25
- ],
10
+ docs: {
11
+ description: {
12
+ component: `
13
+ The \`Slider\` component wraps Mantine's Slider to support a premium design system, a bidirectional input state,
14
+ custom min/max labels, step indicators, and strict states like error, disabled, and read-only.
15
+
16
+ ### Architecture
17
+ The component uses Recursica's unified \`FormControlWrapper\` and \`<WithReadOnlyWrapper>\` to render consistent form layouts (stacked, side-by-side) and read-only representations.
18
+ All visual properties map perfectly to token values inside \`Slider.module.css\`.
19
+ `,
20
+ },
21
+ },
22
+ },
23
+ argTypes: {
24
+ ...formControlArgTypes,
25
+ disabled: {
26
+ control: "boolean",
27
+ description: "Disables both the slider track and the text input field.",
28
+ },
29
+ error: {
30
+ control: "text",
31
+ description:
32
+ "Places the slider in an error state with custom border/icon highlights.",
33
+ },
34
+ required: {
35
+ control: "boolean",
36
+ },
37
+ label: {
38
+ control: "text",
39
+ description: "Outer form control label.",
40
+ },
41
+ assistiveText: {
42
+ control: "text",
43
+ description: "Assistive text rendered below or beside the component.",
44
+ },
45
+ readOnly: {
46
+ control: "boolean",
47
+ description: "Puts the component in static read-only mode.",
48
+ },
49
+ showInput: {
50
+ control: "boolean",
51
+ description: "Controls whether the numeric input box is visible.",
52
+ },
53
+ showMinMaxLabels: {
54
+ control: "boolean",
55
+ description: "Toggles rendering of min/max labels below the track.",
26
56
  },
27
57
  },
28
58
  };
29
59
 
30
60
  export default meta;
61
+
31
62
  type Story = StoryObj<typeof Slider>;
32
63
 
33
64
  export const Default: Story = {
34
- render: () => <ComingSoon componentName="Slider" />,
65
+ args: {
66
+ label: "Auditory Threshold",
67
+ assistiveText: "Specify the maximum decibel frequency boundary.",
68
+ defaultValue: 60,
69
+ min: 10,
70
+ max: 100,
71
+ step: 1,
72
+ showMinMaxLabels: true,
73
+ },
74
+ };
75
+
76
+ export const WithInputField: Story = {
77
+ args: {
78
+ ...Default.args,
79
+ showInput: true,
80
+ },
81
+ };
82
+
83
+ export const SideBySideLayout: Story = {
84
+ args: {
85
+ ...Default.args,
86
+ formLayout: "side-by-side",
87
+ },
88
+ };
89
+
90
+ export const Disabled: Story = {
91
+ args: {
92
+ label: "Decommissioned Server Node",
93
+ assistiveText: "Modifications to this environment are frozen.",
94
+ defaultValue: 35,
95
+ disabled: false,
96
+ },
97
+ };
98
+
99
+ export const ErrorState: Story = {
100
+ args: {
101
+ label: "Core Temperature Alert",
102
+ assistiveText:
103
+ "Severe core degradation across the hypervisor socket cluster.",
104
+ defaultValue: 85,
105
+ error: "Thermal overload threshold exceeded.",
106
+ required: true,
107
+ },
108
+ };
109
+
110
+ export const StaticReadOnly: Story = {
111
+ args: {
112
+ label: "System Calibration Metrics",
113
+ assistiveText:
114
+ "Frozen baseline calibrations derived during initial staging.",
115
+ value: 65,
116
+ readOnly: true,
117
+ },
118
+ };
119
+
120
+ export const EditableReadOnly: Story = {
121
+ args: {
122
+ label: "Adaptive Node Output",
123
+ assistiveText:
124
+ "Click edit to unlock bidirectional input parameter boundaries.",
125
+ defaultValue: 15,
126
+ readOnly: true,
127
+ labelWithEditIcon: true,
128
+ },
129
+ };
130
+
131
+ export const WithMarks: Story = {
132
+ args: {
133
+ label: "Interactive Marks Map",
134
+ defaultValue: 50,
135
+ min: 0,
136
+ max: 100,
137
+ step: 10,
138
+ marks: [
139
+ { value: 0, label: "0%" },
140
+ { value: 25, label: "25%" },
141
+ { value: 50, label: "50%" },
142
+ { value: 75, label: "75%" },
143
+ { value: 100, label: "100%" },
144
+ ],
145
+ showMinMaxLabels: false,
146
+ },
147
+ };
148
+
149
+ export const FormLayouts: Story = {
150
+ render: () => (
151
+ <div
152
+ style={{
153
+ display: "flex",
154
+ flexDirection: "column",
155
+ gap: "2.5rem",
156
+ maxWidth: 600,
157
+ }}
158
+ >
159
+ <Slider
160
+ label="Stacked Layout"
161
+ assistiveText="This is the standard top-to-bottom stacked form layout."
162
+ defaultValue={40}
163
+ formLayout="stacked"
164
+ />
165
+ <Slider
166
+ label="Side-by-Side Layout"
167
+ assistiveText="This is the side-by-side layout aligning label beside control."
168
+ defaultValue={60}
169
+ formLayout="side-by-side"
170
+ />
171
+ </div>
172
+ ),
35
173
  };
@@ -1,8 +1,286 @@
1
- import React from "react";
2
- import "./Slider.module.css";
1
+ import React, { forwardRef, useState, useEffect } 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
+ type RecursicaOverStyled,
10
+ } from "../../utils/filterStylingProps";
11
+ import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
12
+ import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
3
13
 
4
- export type SliderProps = React.HTMLAttributes<HTMLDivElement>;
14
+ import styles from "./Slider.module.css";
5
15
 
6
- export const Slider: React.FC<SliderProps> = (props) => {
7
- return <div {...props}>Slider</div>;
16
+ import { type RecursicaSliderProps as BaseRecursicaSliderProps } from "@recursica/adapter-common";
17
+
18
+ export interface RecursicaSliderProps
19
+ extends Omit<
20
+ MuiSliderProps,
21
+ "size" | "color" | "classes" | "onChange" | "onChangeCommitted"
22
+ >,
23
+ Omit<
24
+ RecursicaFormControlWrapperProps,
25
+ | "controlMaxWidth"
26
+ | "controlMinWidth"
27
+ | "error"
28
+ | "required"
29
+ | "withAsterisk"
30
+ | keyof MuiSliderProps
31
+ >,
32
+ ReadOnlyControlProps,
33
+ BaseRecursicaSliderProps {}
34
+
35
+ export type SliderProps = RecursicaOverStyled<RecursicaSliderProps>;
36
+
37
+ /**
38
+ * Custom Read-Only visual representation of the Slider value.
39
+ * Utilizes component-specific read-only typography variables.
40
+ */
41
+ const SliderReadOnlyValue: React.FC<{ value: number }> = ({ value }) => {
42
+ return <div className={styles.readOnlyValue}>{value}</div>;
8
43
  };
44
+
45
+ /**
46
+ * Recursica Slider component wrapping Mui's Slider.
47
+ *
48
+ * Implements a bidirectional text input field next to the slider track, responsive layouts,
49
+ * custom typography-bound min/max labels, an optional leading icon, and an explicit read-only layout.
50
+ */
51
+ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
52
+ function Slider(props, ref) {
53
+ const {
54
+ overStyled = false,
55
+ formLayout = "stacked",
56
+
57
+ // Label & Wrapper Maps
58
+ labelSize,
59
+ labelAlignment,
60
+ labelOptionalText,
61
+ labelWithEditIcon,
62
+ labelActionArea,
63
+ onLabelEditClick,
64
+
65
+ label,
66
+ tooltipLabel,
67
+ assistiveText,
68
+ assistiveWithIcon,
69
+ error,
70
+ required,
71
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
72
+ withAsterisk,
73
+ id,
74
+ className,
75
+ style,
76
+ disabled,
77
+ readOnly,
78
+ readOnlyComponent,
79
+ emptyValueComponent,
80
+ value,
81
+ defaultValue,
82
+ icon,
83
+ showInput = false,
84
+ showMinMaxLabels = true,
85
+ min = 0,
86
+ max = 100,
87
+ step = 1,
88
+ onChange,
89
+ onChangeEnd,
90
+ ...rest
91
+ } = props;
92
+
93
+ // Bidirectional state linking the slider track value to the input field string representation
94
+ const [internalValue, setInternalValue] = useState<number>(() => {
95
+ if (value !== undefined) return Array.isArray(value) ? value[0] : value;
96
+ if (defaultValue !== undefined)
97
+ return Array.isArray(defaultValue) ? defaultValue[0] : defaultValue;
98
+ return min;
99
+ });
100
+
101
+ const resolvedValue =
102
+ value !== undefined
103
+ ? Array.isArray(value)
104
+ ? value[0]
105
+ : value
106
+ : internalValue;
107
+ const [inputValue, setInputValue] = useState<string>(
108
+ resolvedValue.toString(),
109
+ );
110
+
111
+ // Synchronize text input whenever the slider value changes
112
+ useEffect(() => {
113
+ setInputValue(resolvedValue.toString());
114
+ }, [resolvedValue]);
115
+
116
+ const handleValueChange = (_e: Event, val: number | number[]) => {
117
+ const singleVal = Array.isArray(val) ? val[0] : val;
118
+ if (value === undefined) {
119
+ setInternalValue(singleVal);
120
+ }
121
+ onChange?.(singleVal);
122
+ };
123
+
124
+ const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
125
+ const valStr = e.target.value;
126
+ setInputValue(valStr);
127
+
128
+ const parsed = parseFloat(valStr);
129
+ if (!isNaN(parsed)) {
130
+ // Clamp input value to bounds
131
+ const clamped = Math.max(min, Math.min(max, parsed));
132
+ handleValueChange(null as any, clamped);
133
+ }
134
+ };
135
+
136
+ const handleInputBlur = () => {
137
+ setInputValue(resolvedValue.toString());
138
+ };
139
+
140
+ const sanitizedProps = filterStylingProps(rest, overStyled);
141
+ const restRecord = sanitizedProps as Record<string, unknown>;
142
+
143
+ // Delete prohibited sizing hooks from bypassing variables natively
144
+ delete restRecord["size"];
145
+ delete restRecord["color"];
146
+ delete restRecord["wrapperProps"];
147
+
148
+ // Securely map core native blocks down ensuring nested CSS modules map precisely
149
+ const mergedClassNames: Partial<Record<string, string>> = {
150
+ root: styles.sliderRoot,
151
+ rail: styles.sliderTrack,
152
+ track: styles.sliderBar,
153
+ thumb: styles.sliderThumb,
154
+ mark: styles.sliderMark,
155
+ markLabel: styles.sliderMarkLabel,
156
+ valueLabel: styles.sliderTooltip,
157
+ };
158
+
159
+ const classNamesProp = restRecord.classNames;
160
+ if (
161
+ classNamesProp &&
162
+ typeof classNamesProp === "object" &&
163
+ !Array.isArray(classNamesProp)
164
+ ) {
165
+ const o = classNamesProp as Partial<Record<string, string>>;
166
+ mergedClassNames.root = o.root
167
+ ? `${styles.sliderRoot} ${o.root}`
168
+ : styles.sliderRoot;
169
+ mergedClassNames.rail = o.track
170
+ ? `${styles.sliderTrack} ${o.track}`
171
+ : styles.sliderTrack;
172
+ mergedClassNames.track = o.bar
173
+ ? `${styles.sliderBar} ${o.bar}`
174
+ : styles.sliderBar;
175
+ mergedClassNames.thumb = o.thumb
176
+ ? `${styles.sliderThumb} ${o.thumb}`
177
+ : styles.sliderThumb;
178
+ mergedClassNames.mark = o.mark
179
+ ? `${styles.sliderMark} ${o.mark}`
180
+ : styles.sliderMark;
181
+ mergedClassNames.markLabel = o.markLabel
182
+ ? `${styles.sliderMarkLabel} ${o.markLabel}`
183
+ : styles.sliderMarkLabel;
184
+ }
185
+
186
+ const wrapperClass = className
187
+ ? `${styles.layoutOverride} ${className}`
188
+ : styles.layoutOverride;
189
+
190
+ const leadingIcon = icon ? (
191
+ <span className={styles.iconWrapper} aria-hidden>
192
+ {icon}
193
+ </span>
194
+ ) : null;
195
+
196
+ return (
197
+ <WithReadOnlyWrapper
198
+ ref={ref}
199
+ className={wrapperClass}
200
+ style={style as React.CSSProperties}
201
+ controlMaxWidth={undefined}
202
+ controlMinWidth={undefined}
203
+ overStyled={overStyled as true}
204
+ formLayout={formLayout}
205
+ labelSize={labelSize}
206
+ labelAlignment={labelAlignment}
207
+ labelOptionalText={labelOptionalText}
208
+ labelWithEditIcon={labelWithEditIcon}
209
+ labelActionArea={labelActionArea}
210
+ onLabelEditClick={onLabelEditClick}
211
+ label={label}
212
+ assistiveText={assistiveText}
213
+ assistiveWithIcon={assistiveWithIcon}
214
+ error={error as any}
215
+ required={required}
216
+ id={id}
217
+ readOnly={readOnly}
218
+ readOnlyComponent={readOnlyComponent || SliderReadOnlyValue}
219
+ emptyValueComponent={emptyValueComponent}
220
+ readOnlyType="text"
221
+ readOnlyValue={resolvedValue}
222
+ readOnlyNativeProps={{ value: resolvedValue }}
223
+ activeComponent={
224
+ <div
225
+ className={styles.sliderContainer}
226
+ data-form-layout={formLayout}
227
+ data-disabled={disabled ? "true" : undefined}
228
+ data-error={error ? "true" : undefined}
229
+ >
230
+ {leadingIcon}
231
+
232
+ {showMinMaxLabels && (
233
+ <span className={styles.minMaxGuide}>{min}</span>
234
+ )}
235
+
236
+ <div className={styles.sliderTrackWrapper}>
237
+ <MuiSlider
238
+ classes={mergedClassNames}
239
+ disabled={disabled}
240
+ value={resolvedValue}
241
+ onChange={handleValueChange}
242
+ onChangeCommitted={onChangeEnd as any}
243
+ min={min}
244
+ max={max}
245
+ step={step}
246
+ valueLabelDisplay={tooltipLabel === null ? "off" : "auto"}
247
+ valueLabelFormat={
248
+ typeof tooltipLabel === "function"
249
+ ? (tooltipLabel as any)
250
+ : undefined
251
+ }
252
+ {...(sanitizedProps as unknown as MuiSliderProps)}
253
+ />
254
+ </div>
255
+
256
+ <div className={styles.rightGuideContainer}>
257
+ {!showInput && (
258
+ <span className={styles.currentValue}>{resolvedValue}</span>
259
+ )}
260
+ {showMinMaxLabels && (
261
+ <span className={styles.minMaxGuide}>{max}</span>
262
+ )}
263
+ </div>
264
+
265
+ {showInput && (
266
+ <input
267
+ type="number"
268
+ className={styles.inputField}
269
+ value={inputValue}
270
+ onChange={handleInputChange}
271
+ onBlur={handleInputBlur}
272
+ min={min}
273
+ max={max}
274
+ step={step ?? undefined}
275
+ disabled={disabled}
276
+ data-error={error ? "true" : undefined}
277
+ />
278
+ )}
279
+ </div>
280
+ }
281
+ />
282
+ );
283
+ },
284
+ );
285
+
286
+ Slider.displayName = "Slider";
@@ -17,32 +17,11 @@ const meta: Meta<StackStoryProps> = {
17
17
  "Stack is a flex vertical layout container that maps directly to Mantine's Stack component allowing safe layout property passing.",
18
18
  },
19
19
  },
20
- controls: {
21
- include: [
22
- "layer",
23
- "withLayer",
24
- "gap",
25
- "alignItems",
26
- "justifyContent",
27
- "defaultChecked",
28
- "children",
29
- "component",
30
- "variant",
31
- "size",
32
- "icon",
33
- "disabled",
34
- "href",
35
- "onClick",
36
- "onChange",
37
- "value",
38
- "checked",
39
- ],
40
- },
41
20
  },
42
21
  args: {
43
22
  gap: "rec-default",
44
- alignItems: "stretch",
45
- justifyContent: "flex-start",
23
+ align: "stretch",
24
+ justify: "flex-start",
46
25
  },
47
26
  argTypes: {
48
27
  gap: {
@@ -63,12 +42,12 @@ const meta: Meta<StackStoryProps> = {
63
42
  ],
64
43
  description: "Gap between elements",
65
44
  },
66
- alignItems: {
45
+ align: {
67
46
  control: "select",
68
47
  options: ["flex-start", "center", "flex-end", "stretch"],
69
48
  description: "Align-items property",
70
49
  },
71
- justifyContent: {
50
+ justify: {
72
51
  control: "select",
73
52
  options: [
74
53
  "flex-start",
@@ -4,16 +4,12 @@ import {
4
4
  type StackProps as MUIStackProps,
5
5
  } from "@mui/material";
6
6
  import {
7
- type RecursicaSpacing,
8
7
  SPACING_MAP,
9
8
  type OmitSx,
10
9
  filterSxProp,
11
10
  } from "../../utils/filterStylingProps";
12
11
 
13
- export interface RecursicaStackProps {
14
- children?: React.ReactNode;
15
- gap?: MUIStackProps["spacing"] | RecursicaSpacing;
16
- }
12
+ import { type RecursicaStackProps } from "@recursica/adapter-common";
17
13
 
18
14
  export type StackProps = OmitSx<
19
15
  Omit<MUIStackProps, "spacing"> & RecursicaStackProps
@@ -0,0 +1,4 @@
1
+ # Stepper Implementation Notes
2
+
3
+ - **Compositional API Dropped:** Mantine manages stepper state and content via `<Stepper.Step>` and `<Stepper.Completed>`. MUI delegates content rendering to the developer and focuses purely on the stepper visual layout using `<Step>`, `<StepLabel>`, etc.
4
+ - **Monolithic API Adopted:** Following architectural review, we have abandoned the fabricated context wrappers for `mui-adapter`. We now natively export `Stepper`, `Step`, `StepLabel`, `StepButton`, and `StepConnector` wrapping their `@mui/material` counterparts. Developers are expected to manage the active step logic and content rendering outside the `Stepper` component, consistent with MUI patterns. Storybook tests have been updated to reflect this divergence while retaining core visual compatibility.