@recursica/mui-adapter 0.34.1 → 0.34.4

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 (76) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/index.d.ts +219 -154
  3. package/dist/mui-adapter.cjs +55 -55
  4. package/dist/mui-adapter.cjs.map +1 -1
  5. package/dist/mui-adapter.css +1 -1
  6. package/dist/mui-adapter.js +3383 -3440
  7. package/dist/mui-adapter.js.map +1 -1
  8. package/package.json +5 -4
  9. package/src/OverStyling.tsx +2 -2
  10. package/src/components/Accordion/Accordion.test.tsx +1 -0
  11. package/src/components/AssistiveElement/AssistiveElement.test.tsx +1 -0
  12. package/src/components/Autocomplete/Autocomplete.test.tsx +1 -0
  13. package/src/components/Avatar/Avatar.test.tsx +1 -0
  14. package/src/components/Badge/Badge.test.tsx +1 -0
  15. package/src/components/Box/Box.test.tsx +1 -0
  16. package/src/components/Breadcrumb/Breadcrumb.test.tsx +1 -0
  17. package/src/components/Button/BUTTON_IMPLEMENTATION_NOTES.md +10 -0
  18. package/src/components/Button/Button.module.css +1 -0
  19. package/src/components/Button/Button.styleIsolation.dom.test.tsx +98 -0
  20. package/src/components/Card/Card.test.tsx +1 -0
  21. package/src/components/Checkbox/Checkbox.test.tsx +1 -0
  22. package/src/components/Chip/Chip.stories.tsx +11 -0
  23. package/src/components/Chip/Chip.test.tsx +1 -0
  24. package/src/components/Container/Container.test.tsx +1 -0
  25. package/src/components/DatePicker/DatePicker.test.tsx +1 -0
  26. package/src/components/Dropdown/Dropdown.test.tsx +1 -0
  27. package/src/components/FileInput/FileInput.test.tsx +1 -0
  28. package/src/components/FileUpload/FileUpload.test.tsx +1 -0
  29. package/src/components/Flex/Flex.test.tsx +1 -0
  30. package/src/components/Flex/Flex.tsx +21 -4
  31. package/src/components/FormControlLayout/FormControlLayout.test.tsx +1 -0
  32. package/src/components/FormControlWrapper/FormControlWrapper.test.tsx +1 -0
  33. package/src/components/Grid/Grid.stories.tsx +38 -62
  34. package/src/components/Grid/Grid.test.tsx +1 -0
  35. package/src/components/Grid/Grid.tsx +59 -144
  36. package/src/components/Grid/IMPLEMENTATION_NOTES.md +11 -11
  37. package/src/components/Grid/USAGE.md +8 -6
  38. package/src/components/Group/Group.test.tsx +1 -0
  39. package/src/components/Group/Group.tsx +24 -2
  40. package/src/components/HoverCard/HoverCard.test.tsx +1 -0
  41. package/src/components/Label/Label.test.tsx +1 -0
  42. package/src/components/Link/Link.test.tsx +1 -0
  43. package/src/components/Loader/Loader.test.tsx +1 -0
  44. package/src/components/Menu/Menu.test.tsx +1 -0
  45. package/src/components/Modal/Modal.test.tsx +1 -0
  46. package/src/components/NumberInput/NumberInput.test.tsx +1 -0
  47. package/src/components/Pagination/Pagination.test.tsx +1 -0
  48. package/src/components/Panel/Panel.test.tsx +1 -0
  49. package/src/components/Popover/Popover.test.tsx +1 -0
  50. package/src/components/Radio/Radio.test.tsx +1 -0
  51. package/src/components/ReadOnlyField/ReadOnlyField.test.tsx +1 -0
  52. package/src/components/SegmentedControl/SegmentedControl.test.tsx +1 -0
  53. package/src/components/Slider/Slider.test.tsx +1 -0
  54. package/src/components/Stack/Stack.stories.tsx +9 -9
  55. package/src/components/Stack/Stack.test.tsx +1 -0
  56. package/src/components/Stack/Stack.tsx +15 -14
  57. package/src/components/Stack/USAGE.md +1 -1
  58. package/src/components/Stepper/Stepper.test.tsx +1 -0
  59. package/src/components/Switch/Switch.stories.tsx +1 -1
  60. package/src/components/Switch/Switch.test.tsx +1 -0
  61. package/src/components/Table/Table.test.tsx +1 -0
  62. package/src/components/Tabs/Tabs.test.tsx +1 -0
  63. package/src/components/Text/Text.stories.tsx +3 -16
  64. package/src/components/Text/Text.test.tsx +1 -0
  65. package/src/components/TextArea/TextArea.test.tsx +1 -0
  66. package/src/components/TextField/TextField.test.tsx +1 -0
  67. package/src/components/TimePicker/TimePicker.test.tsx +1 -0
  68. package/src/components/Timeline/Timeline.test.tsx +1 -0
  69. package/src/components/Title/Title.stories.tsx +3 -16
  70. package/src/components/Title/Title.test.tsx +1 -0
  71. package/src/components/Toast/Toast.test.tsx +1 -0
  72. package/src/components/Tooltip/Tooltip.test.tsx +1 -0
  73. package/src/components/TransferList/TransferList.test.tsx +1 -0
  74. package/src/components/Tree/Tree.test.tsx +1 -0
  75. package/src/components/Typography/Typography.test.tsx +1 -0
  76. package/src/utils/filterStylingProps.test.ts +85 -0
@@ -1,22 +1,30 @@
1
1
  /**
2
2
  * Grid layout wrapper.
3
3
  *
4
- * NOTE: MUI merges "container" and "item" into a single Grid component (no separate
5
- * Grid.Col in the underlying library, and no native `order`, `justifyContent`,
6
- * `alignItems`, or breakpoint-visibility support). To preserve API parity with the
7
- * mantine-adapter (Grid + Grid.Col dot notation, matching Mantine's own Grid/Grid.Col),
8
- * this file splits MUI's single component back into two wrappers: Grid always renders
9
- * MUI's `<Grid container>`, GridCol always renders MUI's `<Grid>` in item mode.
4
+ * MUI merges "container" and "item" into a single `Grid` component (no separate Grid.Col,
5
+ * unlike Mantine). To preserve the Grid/Grid.Col dot-notation shape across adapters, this
6
+ * file splits MUI's single component back into two thin wrappers: Grid always renders MUI's
7
+ * `<Grid container>`, GridCol always renders a plain MUI `<Grid>` (item mode).
8
+ *
9
+ * Per the layout-components rule, both wrappers simply pass through MUI's own Grid props
10
+ * (`size`, `offset`, `spacing`, `columns`, `direction`, `wrap`) with no Recursica renaming.
11
+ * MUI has no per-item "grow to fill remaining space" container flag like Mantine's `grow`;
12
+ * use MUI's own `size="grow"` on individual columns instead. `visibleFrom`/`hiddenFrom`
13
+ * don't exist in MUI at all, so — per the rule that a missing kit feature is built following
14
+ * Mantine's own shape — they're added here via CSS classes, keyed on MUI's own breakpoint
15
+ * scale (`xs`/`sm`/`md`/`lg`/`xl`).
16
+ *
17
+ * `justifyContent`/`alignItems` (container) and `order` (item) are typed on `MuiGridProps`
18
+ * (inherited generically from `SystemProps`) but MUI's Grid style generator — verified by
19
+ * reading `@mui/system`'s `gridGenerator.js`/`createGrid.js` — only wires up `size`, `offset`,
20
+ * `columns`, `spacing`/`rowSpacing`/`columnSpacing`, `direction`, and `wrap`; passing these
21
+ * three straight through would silently no-op. They're pulled out and applied via inline
22
+ * `style` instead, still using MUI's own native names.
10
23
  *
11
24
  * Like Flex, Stack, Group, and Container, this is a primitive layout component and
12
25
  * does not use the `RecursicaOverStyled` gatekeeper — only the `sx` prop is stripped.
13
26
  */
14
- import {
15
- createContext,
16
- forwardRef,
17
- useContext,
18
- type CSSProperties,
19
- } from "react";
27
+ import { forwardRef, type CSSProperties } from "react";
20
28
  import { Grid as MuiGrid, type GridProps as MuiGridProps } from "@mui/material";
21
29
  import {
22
30
  SPACING_MAP,
@@ -26,81 +34,9 @@ import {
26
34
  } from "../../utils/filterStylingProps";
27
35
  import styles from "./Grid.module.css";
28
36
 
29
- import {
30
- type RecursicaGridProps,
31
- type RecursicaGridColProps,
32
- } from "@recursica/adapter-common";
33
-
34
37
  type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl";
35
- type RecursicaBreakpoint = "base" | Breakpoint;
36
-
37
- const GridContext = createContext<{ grow: boolean }>({ grow: false });
38
-
39
- /** Remaps the Recursica-only "base" breakpoint key to MUI's "xs" (its smallest breakpoint). */
40
- function remapBase<T>(
41
- value: T | Partial<Record<RecursicaBreakpoint, T>> | undefined,
42
- ): T | Partial<Record<Breakpoint, T>> | undefined {
43
- if (value === undefined || typeof value !== "object") {
44
- return value as T | undefined;
45
- }
46
- const { base, ...rest } = value as Partial<Record<RecursicaBreakpoint, T>>;
47
- return base !== undefined
48
- ? ({ xs: base, ...rest } as Partial<Record<Breakpoint, T>>)
49
- : (rest as Partial<Record<Breakpoint, T>>);
50
- }
51
-
52
- /**
53
- * Recursica's "auto" (grow to fill remaining space) and "content" (size to content)
54
- * are the inverse of MUI's own "auto" (size to content) and "grow" (fill remaining
55
- * space) keywords.
56
- */
57
- function mapSpanValue(
58
- value: number | "auto" | "content" | undefined,
59
- ): number | "auto" | "grow" | undefined {
60
- if (value === "auto") return "grow";
61
- if (value === "content") return "auto";
62
- return value;
63
- }
64
-
65
- function mapSpan(span: RecursicaGridColProps["span"]): MuiGridProps["size"] {
66
- const remapped = remapBase(span);
67
- if (remapped === undefined || typeof remapped !== "object") {
68
- return mapSpanValue(remapped as number | "auto" | "content" | undefined);
69
- }
70
- const mapped: Partial<Record<Breakpoint, number | "auto" | "grow">> = {};
71
- (
72
- Object.entries(remapped) as [Breakpoint, number | "auto" | "content"][]
73
- ).forEach(([key, value]) => {
74
- mapped[key] = mapSpanValue(value);
75
- });
76
- return mapped as MuiGridProps["size"];
77
- }
78
-
79
- function mapOffset(
80
- offset: RecursicaGridColProps["offset"],
81
- ): MuiGridProps["offset"] {
82
- return remapBase(offset) as MuiGridProps["offset"];
83
- }
84
-
85
- /**
86
- * `order` has no native MUI Grid equivalent. A fixed number is applied directly.
87
- * A responsive object is NOT fully supported in this v1 — the smallest specified
88
- * breakpoint's value is applied as a single static order (documented in
89
- * IMPLEMENTATION_NOTES.md), rather than building bespoke per-breakpoint CSS for it.
90
- */
91
- function resolveOrder(
92
- order: RecursicaGridColProps["order"],
93
- ): number | undefined {
94
- if (order === undefined || typeof order === "number") {
95
- return order;
96
- }
97
- const remapped = remapBase(order) as Partial<Record<Breakpoint, number>>;
98
- return (
99
- remapped.xs ?? remapped.sm ?? remapped.md ?? remapped.lg ?? remapped.xl
100
- );
101
- }
102
38
 
103
- const HIDDEN_FROM_CLASS: Partial<Record<Breakpoint, string>> = {
39
+ const HIDDEN_FROM_CLASS: Record<Breakpoint, string> = {
104
40
  xs: styles.hiddenFromXs,
105
41
  sm: styles.hiddenFromSm,
106
42
  md: styles.hiddenFromMd,
@@ -108,7 +44,7 @@ const HIDDEN_FROM_CLASS: Partial<Record<Breakpoint, string>> = {
108
44
  xl: styles.hiddenFromXl,
109
45
  };
110
46
 
111
- // "xs"/"base" intentionally absent: visible from the smallest breakpoint means never hidden.
47
+ // "xs" intentionally absent: visible from the smallest breakpoint means never hidden.
112
48
  const VISIBLE_FROM_CLASS: Partial<Record<Breakpoint, string>> = {
113
49
  sm: styles.visibleFromSm,
114
50
  md: styles.visibleFromMd,
@@ -116,56 +52,47 @@ const VISIBLE_FROM_CLASS: Partial<Record<Breakpoint, string>> = {
116
52
  xl: styles.visibleFromXl,
117
53
  };
118
54
 
119
- function normalizeBreakpoint(bp: RecursicaBreakpoint): Breakpoint {
120
- return bp === "base" ? "xs" : bp;
121
- }
122
-
123
55
  // ============================================================
124
56
  // GRID
125
57
  // ============================================================
126
58
 
127
59
  export type GridProps = WithRecursicaSpacing<
128
- OmitSx<Omit<MuiGridProps, "container" | "size" | "offset">> &
129
- RecursicaGridProps
130
- >;
60
+ OmitSx<Omit<MuiGridProps, "container" | "justifyContent" | "alignItems">>
61
+ > & {
62
+ /** Sets `justify-content` on the container. Applied via inline style — see notes above. */
63
+ justifyContent?: CSSProperties["justifyContent"];
64
+ /** Sets `align-items` on the container. Applied via inline style — see notes above. */
65
+ alignItems?: CSSProperties["alignItems"];
66
+ };
131
67
 
132
68
  const GridBase = forwardRef<HTMLDivElement, GridProps>(function Grid(
133
69
  {
134
70
  children,
135
- gap = "rec-default",
136
- columns = 12,
137
- grow = false,
138
- justify,
139
- align,
71
+ spacing = "rec-default",
72
+ justifyContent,
73
+ alignItems,
140
74
  style,
141
75
  ...rest
142
76
  },
143
77
  ref,
144
78
  ) {
145
79
  const safeProps = filterSxProp(rest as Record<string, unknown>);
146
- const resolvedGap =
147
- typeof gap === "string" && gap in SPACING_MAP
148
- ? SPACING_MAP[gap as keyof typeof SPACING_MAP]
149
- : gap;
80
+ const resolvedSpacing =
81
+ typeof spacing === "string" && spacing in SPACING_MAP
82
+ ? SPACING_MAP[spacing as keyof typeof SPACING_MAP]
83
+ : spacing;
150
84
 
151
85
  return (
152
- <GridContext.Provider value={{ grow }}>
153
- <MuiGrid
154
- ref={ref}
155
- {...(safeProps as unknown as MuiGridProps)}
156
- container
157
- columns={columns}
158
- spacing={resolvedGap}
159
- className={styles.root}
160
- style={{
161
- justifyContent: justify,
162
- alignItems: align,
163
- ...(style as CSSProperties),
164
- }}
165
- >
166
- {children}
167
- </MuiGrid>
168
- </GridContext.Provider>
86
+ <MuiGrid
87
+ ref={ref}
88
+ {...(safeProps as unknown as MuiGridProps)}
89
+ container
90
+ spacing={resolvedSpacing}
91
+ className={styles.root}
92
+ style={{ justifyContent, alignItems, ...(style as CSSProperties) }}
93
+ >
94
+ {children}
95
+ </MuiGrid>
169
96
  );
170
97
  });
171
98
  GridBase.displayName = "Grid";
@@ -175,33 +102,27 @@ GridBase.displayName = "Grid";
175
102
  // ============================================================
176
103
 
177
104
  export type GridColProps = WithRecursicaSpacing<
178
- OmitSx<Omit<MuiGridProps, "container" | "size" | "offset">> &
179
- RecursicaGridColProps
180
- >;
105
+ OmitSx<Omit<MuiGridProps, "container" | "order">>
106
+ > & {
107
+ /** Sets the CSS `order` property. Applied via inline style — see notes above. */
108
+ order?: number;
109
+ /** Hides the column below the given breakpoint. MUI has no native equivalent. */
110
+ visibleFrom?: Breakpoint;
111
+ /** Hides the column above the given breakpoint. MUI has no native equivalent. */
112
+ hiddenFrom?: Breakpoint;
113
+ };
181
114
 
182
115
  export const GridCol = forwardRef<HTMLDivElement, GridColProps>(
183
116
  function GridCol(
184
- {
185
- children,
186
- span,
187
- offset,
188
- order,
189
- visibleFrom,
190
- hiddenFrom,
191
- style,
192
- className,
193
- ...rest
194
- },
117
+ { children, order, visibleFrom, hiddenFrom, style, className, ...rest },
195
118
  ref,
196
119
  ) {
197
- const { grow } = useContext(GridContext);
198
120
  const safeProps = filterSxProp(rest as Record<string, unknown>);
199
- const resolvedOrder = resolveOrder(order);
200
121
 
201
122
  const visibilityClass = visibleFrom
202
- ? VISIBLE_FROM_CLASS[normalizeBreakpoint(visibleFrom)]
123
+ ? VISIBLE_FROM_CLASS[visibleFrom]
203
124
  : hiddenFrom
204
- ? HIDDEN_FROM_CLASS[normalizeBreakpoint(hiddenFrom)]
125
+ ? HIDDEN_FROM_CLASS[hiddenFrom]
205
126
  : undefined;
206
127
 
207
128
  const finalClassName = [styles.col, visibilityClass, className]
@@ -211,15 +132,9 @@ export const GridCol = forwardRef<HTMLDivElement, GridColProps>(
211
132
  return (
212
133
  <MuiGrid
213
134
  ref={ref}
214
- size={mapSpan(span)}
215
- offset={mapOffset(offset)}
216
135
  className={finalClassName}
217
136
  {...(safeProps as unknown as MuiGridProps)}
218
- style={{
219
- order: resolvedOrder,
220
- ...(grow ? { flexGrow: 1 } : {}),
221
- ...(style as CSSProperties),
222
- }}
137
+ style={{ order, ...(style as CSSProperties) }}
223
138
  >
224
139
  {children}
225
140
  </MuiGrid>
@@ -1,16 +1,16 @@
1
1
  # Grid Implementation Notes
2
2
 
3
- MUI has no native Grid/Grid.Col split — MUI's own `Grid` component merges "container" and "item" behavior into one component (toggled by the `container` boolean and a `size` prop). To keep the exact same public API as the mantine-adapter (`Grid` + `Grid.Col` dot notation, matching Mantine's own `Grid`/`Grid.Col`), this file hand-composes two wrappers around that single underlying component: `Grid` always renders `<MuiGrid container>`, `Grid.Col` always renders `<MuiGrid>` in item mode. A `GridContext` (internal, not exported) carries the parent's `grow` flag down to `Grid.Col`, since MUI has no equivalent React context of its own for this and siblings can't share props directly.
3
+ MUI has no native Grid/Grid.Col split — MUI's own `Grid` component merges "container" and "item" behavior into one component (toggled by the `container` boolean and a `size` prop). To keep the same `Grid` + `Grid.Col` dot-notation shape as the mantine-adapter, this file hand-composes two thin wrappers around that single underlying component: `Grid` always renders `<MuiGrid container>`, `Grid.Col` always renders `<MuiGrid>` in item mode. This is a structural convenience only — the props on each wrapper are MUI's own, not a Recursica-defined contract.
4
4
 
5
- Prop mapping details and divergences from a literal 1:1 MUI wrap:
5
+ Per the layout-components rule (no formal Recursica common props definition — layout components simply pass through the underlying kit's own props), this Grid does **not** attempt prop-name parity with the mantine-adapter's Grid. Its public API is MUI's own vocabulary:
6
6
 
7
- - **`gap` → `spacing`**: MUI's own container-spacing prop is `spacing` (not `gutter`, which is Mantine's term). Resolved through the same `rec-*` → `SPACING_MAP` lookup used elsewhere in this adapter.
8
- - **`span` keyword inversion**: Recursica's `"auto"` (fill remaining space) and `"content"` (size to content) are the _inverse_ of MUI's own `size` keywords — MUI's `"auto"` means size-to-content and `"grow"` means fill-remaining-space. `mapSpanValue()` translates between them so the public `span` prop matches Mantine's semantics exactly. Verified against `@mui/system`'s `generateGridSizeStyles` (`grow` → `flexGrow:1`, `auto` → `flexBasis:auto`).
9
- - **`offset`**: Maps directly to MUI's own `offset` prop — same name, same responsive shape and semantics. No translation needed.
10
- - **`"base"` breakpoint key**: Recursica's breakpoint objects (matching Mantine's `Grid.Col` shape) use `base` for the default/smallest value; MUI has no `"base"` key, only `xs` as its smallest breakpoint (`min-width: 0`). `remapBase()` renames `base` → `xs` (an explicit `xs` in the same object wins over `base` if both are present).
11
- - **`order`**: MUI's Grid has no `order` prop at all. A fixed number is applied via inline `style.order` (inline style always wins the cascade, so this works regardless of MUI's generated styles). A responsive object is **not** fully implemented — building full per-breakpoint CSS custom-property cascading for a rarely-used prop wasn't judged worth the added CSS surface for v1. `resolveOrder()` currently just takes the smallest specified breakpoint's value and applies it as a single static order. This is a known, documented gap, not a silent one — revisit if a real per-breakpoint ordering need comes up.
12
- - **`grow`**: MUI's Grid has no equivalent. Mantine's own implementation (and this one) relies on a CSS quirk: setting `flex-grow: 1` on every column in a row only visibly affects the _last, incomplete_ row — fully-filled rows have zero remaining space to grow into. Applied via inline `style.flexGrow` on `Grid.Col`, read from `GridContext`.
13
- - **`visibleFrom` / `hiddenFrom`**: No native MUI Grid mechanism. Implemented via `Grid.module.css` media-query classes, hardcoded to MUI's own default `theme.breakpoints` pixel values (`xs:0, sm:600, md:900, lg:1200, xl:1536`). If the consuming app customizes its MUI theme breakpoints, these thresholds won't follow — structural layout mechanics, not a design token, so this doesn't go through the token pipeline.
14
- - **`justifyContent` / `alignItems`**: MUI's `Grid` does not register these as recognized style-system props the way `Box` does (confirmed by reading `@mui/system`'s `gridGenerator.js` — no generator function reads them), so passing them as bare props would silently do nothing. They're applied via inline `style` instead.
7
+ - **`spacing`** (not Mantine's `gutter`/the old Recursica `gap` alias) — MUI's own container-spacing prop. Still accepts `rec-*` tokens, resolved through the same `SPACING_MAP` lookup used elsewhere in this adapter.
8
+ - **`size`** (not Mantine's `span`) — MUI's own item-sizing prop on `Grid.Col`: a column count, `"auto"` (size to content), `"grow"` (fill remaining space), or a responsive object keyed by MUI's own breakpoints. No inversion/translation against Mantine's `span` semantics.
9
+ - **`offset`** — MUI's own prop, used as-is.
10
+ - **Breakpoint objects** use MUI's own scale (`xs`/`sm`/`md`/`lg`/`xl`) directly. There is no `"base"` alias — `xs` is MUI's smallest breakpoint, same role Mantine's own smallest breakpoint plays.
11
+ - **`grow` (container-level)**: not implemented. Mantine's container `grow` flag ("last row's columns expand to fill available space") has no MUI equivalent, but MUI's own `size="grow"` on individual `Grid.Col`s already covers the same real-world need — set it per-column instead of on the container.
12
+ - **`order`**: MUI types `order` generically (via `SystemProps`) but its Grid style generator (`gridGenerator.js`/`createGrid.js`, read directly to confirm) never wires it up — passing it straight through silently no-ops. Applied here via inline `style.order` instead, single value only (no per-breakpoint object).
13
+ - **`justifyContent` / `alignItems`** (container only): same issue as `order` — typed but not read by MUI's Grid generator (confirmed by reading `gridGenerator.js`: only `size`, `offset`, `columns`, spacing, `direction`, and `wrap` have generator functions). Applied via inline `style` instead, using MUI's own prop names (not Mantine's `justify`/`align`).
14
+ - **`visibleFrom` / `hiddenFrom`**: no native MUI Grid mechanism at all, so — per the rule that a missing kit feature is built following Mantine's own shape — implemented via `Grid.module.css` media-query classes, hardcoded to MUI's own default `theme.breakpoints` pixel values (`xs:0, sm:600, md:900, lg:1200, xl:1536`). If the consuming app customizes its MUI theme breakpoints, these thresholds won't follow — structural layout mechanics, not a design token.
15
15
 
16
- **Cross-adapter parity caveat**: `visibleFrom`/`hiddenFrom` (and the eventual full responsive `order`) are pinned to MUI's default breakpoints here, while the mantine-adapter's equivalent behavior is driven by Mantine's own default breakpoints (576/768/992/1200/1408). The two adapters' Grid stories may show different columns at the exact same viewport width in the `adapter-tester` visual-regression suite as a result — a real, structural difference between the two underlying libraries' breakpoint scales, not a bug in either adapter.
16
+ **Cross-adapter parity caveat**: `visibleFrom`/`hiddenFrom` are pinned to MUI's default breakpoints here, while the mantine-adapter's equivalent behavior is driven by Mantine's own default breakpoints (576/768/992/1200/1408). The two adapters' Grid stories may show different columns at the exact same viewport width in the `adapter-tester` visual-regression suite as a result — a real, structural difference between the two underlying libraries' breakpoint scales, not a bug in either adapter. The two adapters' Grid APIs are also no longer prop-name-identical (`spacing`/`size` here vs. `gutter`/`span` in mantine-adapter) — this is intentional per the layout-components rule; each adapter's Grid speaks its own kit's vocabulary.
@@ -20,9 +20,9 @@ import { Grid } from "@recursica/mui-adapter";
20
20
 
21
21
  export default function Demo() {
22
22
  return (
23
- <Grid gap="rec-default">
24
- <Grid.Col span={6}>Half width</Grid.Col>
25
- <Grid.Col span={{ base: 12, sm: 6, md: 3 }}>Responsive width</Grid.Col>
23
+ <Grid spacing="rec-default">
24
+ <Grid.Col size={6}>Half width</Grid.Col>
25
+ <Grid.Col size={{ xs: 12, sm: 6, md: 3 }}>Responsive width</Grid.Col>
26
26
  </Grid>
27
27
  );
28
28
  }
@@ -44,8 +44,10 @@ All Recursica components in the `@recursica/mui-adapter` package adhere strictly
44
44
 
45
45
  ## 4. Key Integration Features & Constraints
46
46
 
47
- - `gap` controls the spacing between grid items.
48
- - `span` accepts a column count, `"auto"`, `"content"`, or a responsive object (`{ base, sm, md, ... }`).
47
+ This Grid uses MUI's own prop vocabulary directly (see [IMPLEMENTATION_NOTES.md](./IMPLEMENTATION_NOTES.md)) — it is not name-for-name identical to the mantine-adapter's Grid.
48
+
49
+ - `spacing` controls the space between grid items (accepts `rec-*` tokens).
50
+ - `size` accepts a column count, `"auto"`, `"grow"`, or a responsive object (`{ xs, sm, md, ... }`).
49
51
  - `offset` shifts a column by a number of columns.
50
- - `order` accepts a fixed number to control a column's visual order. A responsive object (`{ base, sm, md, ... }`) is **not** fully supported yet — only the smallest specified breakpoint's value is applied.
52
+ - `order` accepts a fixed number to control a column's visual order (single value only, no responsive object).
51
53
  - `visibleFrom`/`hiddenFrom` show or hide a column at the standard breakpoints (600/900/1200/1536px).
@@ -0,0 +1 @@
1
+ // Placeholder for future Group component tests. Add tests here if/when needed.
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Group layout wrapper.
3
+ *
4
+ * NOTE: MUI has no native `<Group>` component. Per the layout-components rule, when a UI kit
5
+ * lacks an equivalent component it's built following a prop definition similar to Mantine's
6
+ * own `Group` (gap/rowGap/columnGap/justify/align/wrap) — this shape is owned locally here,
7
+ * not shared as a formal cross-adapter Recursica contract. It's implemented as a row-direction,
8
+ * wrapping MUI `Stack`.
9
+ */
1
10
  import { forwardRef } from "react";
2
11
  import {
3
12
  Stack as MUIStack,
@@ -10,10 +19,23 @@ import {
10
19
  type WithRecursicaSpacing,
11
20
  } from "../../utils/filterStylingProps";
12
21
 
13
- import { type RecursicaGroupProps } from "@recursica/adapter-common";
22
+ interface GroupOwnProps {
23
+ /** Gap spacing */
24
+ gap?: string | number;
25
+ /** Row gap spacing */
26
+ rowGap?: string | number;
27
+ /** Column gap spacing */
28
+ columnGap?: string | number;
29
+ /** Align items justify properties */
30
+ justify?: React.CSSProperties["justifyContent"];
31
+ /** Align items vertical alignment */
32
+ align?: React.CSSProperties["alignItems"];
33
+ /** Flex-wrap settings */
34
+ wrap?: React.CSSProperties["flexWrap"];
35
+ }
14
36
 
15
37
  export type GroupProps = WithRecursicaSpacing<
16
- OmitSx<Omit<MUIStackProps, "spacing" | "direction"> & RecursicaGroupProps>
38
+ OmitSx<Omit<MUIStackProps, "spacing" | "direction"> & GroupOwnProps>
17
39
  >;
18
40
 
19
41
  export const Group = forwardRef<HTMLDivElement, GroupProps>(function Group(
@@ -0,0 +1 @@
1
+ // Placeholder for future HoverCard component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Label component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Link component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Loader component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Menu component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Modal component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future NumberInput component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Pagination component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Panel component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Popover component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Radio component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future ReadOnlyField component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future SegmentedControl component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Slider component tests. Add tests here if/when needed.
@@ -19,12 +19,12 @@ const meta: Meta<StackStoryProps> = {
19
19
  },
20
20
  },
21
21
  args: {
22
- gap: "rec-default",
23
- align: "stretch",
24
- justify: "flex-start",
22
+ spacing: "rec-default",
23
+ alignItems: "stretch",
24
+ justifyContent: "flex-start",
25
25
  },
26
26
  argTypes: {
27
- gap: {
27
+ spacing: {
28
28
  control: "select",
29
29
  options: [
30
30
  "rec-none",
@@ -40,14 +40,14 @@ const meta: Meta<StackStoryProps> = {
40
40
  "lg",
41
41
  "xl",
42
42
  ],
43
- description: "Gap between elements",
43
+ description: "Space between elements",
44
44
  },
45
- align: {
45
+ alignItems: {
46
46
  control: "select",
47
47
  options: ["flex-start", "center", "flex-end", "stretch"],
48
48
  description: "Align-items property",
49
49
  },
50
- justify: {
50
+ justifyContent: {
51
51
  control: "select",
52
52
  options: [
53
53
  "flex-start",
@@ -81,7 +81,7 @@ export const Default: Story = {
81
81
 
82
82
  export const StaticGapSmall: Story = {
83
83
  args: {
84
- gap: "rec-sm",
84
+ spacing: "rec-sm",
85
85
  },
86
86
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
87
87
  render: ({ withLayer, layer, ...args }: any) => (
@@ -95,7 +95,7 @@ export const StaticGapSmall: Story = {
95
95
 
96
96
  export const StaticGapLarge: Story = {
97
97
  args: {
98
- gap: "rec-xl",
98
+ spacing: "rec-xl",
99
99
  },
100
100
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
101
101
  render: ({ withLayer, layer, ...args }: any) => (
@@ -0,0 +1 @@
1
+ // Placeholder for future Stack component tests. Add tests here if/when needed.
@@ -1,3 +1,10 @@
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
+ */
1
8
  import { forwardRef } from "react";
2
9
  import {
3
10
  Stack as MUIStack,
@@ -10,29 +17,23 @@ import {
10
17
  type WithRecursicaSpacing,
11
18
  } from "../../utils/filterStylingProps";
12
19
 
13
- import { type RecursicaStackProps } from "@recursica/adapter-common";
14
-
15
- export type StackProps = WithRecursicaSpacing<
16
- OmitSx<Omit<MUIStackProps, "spacing"> & RecursicaStackProps>
17
- >;
20
+ export type StackProps = WithRecursicaSpacing<OmitSx<MUIStackProps>>;
18
21
 
19
22
  export const Stack = forwardRef<HTMLDivElement, StackProps>(function Stack(
20
- { children, gap = "rec-default", align, justify, ...rest },
23
+ { children, spacing = "rec-default", ...rest },
21
24
  ref,
22
25
  ) {
23
26
  const safeProps = filterSxProp(rest as Record<string, unknown>);
24
- const resolvedGap =
25
- typeof gap === "string" && gap in SPACING_MAP
26
- ? SPACING_MAP[gap as keyof typeof SPACING_MAP]
27
- : gap;
27
+ const resolvedSpacing =
28
+ typeof spacing === "string" && spacing in SPACING_MAP
29
+ ? SPACING_MAP[spacing as keyof typeof SPACING_MAP]
30
+ : spacing;
28
31
 
29
32
  return (
30
33
  <MUIStack
31
34
  ref={ref}
32
- {...safeProps}
33
- spacing={resolvedGap}
34
- alignItems={align}
35
- justifyContent={justify}
35
+ {...(safeProps as unknown as MUIStackProps)}
36
+ spacing={resolvedSpacing}
36
37
  >
37
38
  {children}
38
39
  </MUIStack>
@@ -20,7 +20,7 @@ import { Stack } from "@recursica/mui-adapter";
20
20
 
21
21
  export default function Demo() {
22
22
  return (
23
- <Stack gap="md" align="stretch">
23
+ <Stack spacing="md" alignItems="stretch">
24
24
  <Text>Item 1</Text>
25
25
  <Text>Item 2</Text>
26
26
  </Stack>
@@ -0,0 +1 @@
1
+ // Placeholder for future Stepper component tests. Add tests here if/when needed.
@@ -77,7 +77,7 @@ export const SideBySideLayout: Story = {
77
77
  export const StaticVariations: Story = {
78
78
  args: {},
79
79
  render: () => (
80
- <Stack gap="xl">
80
+ <Stack spacing="xl">
81
81
  <Switch label="Default Unchecked State" />
82
82
  <Switch label="Checked State" defaultChecked />
83
83
  <Switch label="Disabled Unchecked" disabled />
@@ -0,0 +1 @@
1
+ // Placeholder for future Switch component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Table component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future Tabs component tests. Add tests here if/when needed.
@@ -1,6 +1,5 @@
1
1
  import type { Meta, StoryObj } from "@storybook/react";
2
2
  import { Text } from "./Text";
3
- import { Layer } from "@recursica/adapter-common";
4
3
 
5
4
  const meta: Meta<typeof Text> = {
6
5
  title: "UI-Kit/Text",
@@ -46,25 +45,13 @@ export const Default: Story = {
46
45
  children:
47
46
  "This is standard body typography controlled by the central UI-kit boundaries exclusively.",
48
47
  },
49
- render: ({ ...args }) => (
50
- <Layer layer={0} style={{ padding: "48px" }}>
51
- <Text {...args} />
52
- </Layer>
53
- ),
48
+ render: ({ ...args }) => <Text {...args} />,
54
49
  };
55
50
 
56
51
  export const StaticVariations: Story = {
57
52
  args: {},
58
53
  render: () => (
59
- <Layer
60
- layer={0}
61
- style={{
62
- padding: "48px",
63
- display: "flex",
64
- flexDirection: "column",
65
- gap: "16px",
66
- }}
67
- >
54
+ <div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
68
55
  <Text variant="body">
69
56
  Body (Base paragraph and generic information flow)
70
57
  </Text>
@@ -83,6 +70,6 @@ export const StaticVariations: Story = {
83
70
  <Text variant="subtitle-small">
84
71
  Subtitle Small (Section anchors deep in hierarchy)
85
72
  </Text>
86
- </Layer>
73
+ </div>
87
74
  ),
88
75
  };
@@ -0,0 +1 @@
1
+ // Placeholder for future Text component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future TextArea component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future TextField component tests. Add tests here if/when needed.
@@ -0,0 +1 @@
1
+ // Placeholder for future TimePicker component tests. Add tests here if/when needed.