@recursica/mui-adapter 0.34.1 → 0.34.3
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.
- package/CHANGELOG.md +20 -0
- package/dist/index.d.ts +219 -154
- package/dist/mui-adapter.cjs +55 -55
- package/dist/mui-adapter.cjs.map +1 -1
- package/dist/mui-adapter.css +1 -1
- package/dist/mui-adapter.js +3383 -3440
- package/dist/mui-adapter.js.map +1 -1
- package/package.json +5 -4
- package/src/OverStyling.tsx +2 -2
- package/src/components/Accordion/Accordion.test.tsx +1 -0
- package/src/components/AssistiveElement/AssistiveElement.test.tsx +1 -0
- package/src/components/Autocomplete/Autocomplete.test.tsx +1 -0
- package/src/components/Avatar/Avatar.test.tsx +1 -0
- package/src/components/Badge/Badge.test.tsx +1 -0
- package/src/components/Box/Box.test.tsx +1 -0
- package/src/components/Breadcrumb/Breadcrumb.test.tsx +1 -0
- package/src/components/Button/BUTTON_IMPLEMENTATION_NOTES.md +10 -0
- package/src/components/Button/Button.module.css +1 -0
- package/src/components/Button/Button.styleIsolation.dom.test.tsx +98 -0
- package/src/components/Card/Card.test.tsx +1 -0
- package/src/components/Checkbox/Checkbox.test.tsx +1 -0
- package/src/components/Chip/Chip.test.tsx +1 -0
- package/src/components/Container/Container.test.tsx +1 -0
- package/src/components/DatePicker/DatePicker.test.tsx +1 -0
- package/src/components/Dropdown/Dropdown.test.tsx +1 -0
- package/src/components/FileInput/FileInput.test.tsx +1 -0
- package/src/components/FileUpload/FileUpload.test.tsx +1 -0
- package/src/components/Flex/Flex.test.tsx +1 -0
- package/src/components/Flex/Flex.tsx +21 -4
- package/src/components/FormControlLayout/FormControlLayout.test.tsx +1 -0
- package/src/components/FormControlWrapper/FormControlWrapper.test.tsx +1 -0
- package/src/components/Grid/Grid.stories.tsx +38 -62
- package/src/components/Grid/Grid.test.tsx +1 -0
- package/src/components/Grid/Grid.tsx +59 -144
- package/src/components/Grid/IMPLEMENTATION_NOTES.md +11 -11
- package/src/components/Grid/USAGE.md +8 -6
- package/src/components/Group/Group.test.tsx +1 -0
- package/src/components/Group/Group.tsx +24 -2
- package/src/components/HoverCard/HoverCard.test.tsx +1 -0
- package/src/components/Label/Label.test.tsx +1 -0
- package/src/components/Link/Link.test.tsx +1 -0
- package/src/components/Loader/Loader.test.tsx +1 -0
- package/src/components/Menu/Menu.test.tsx +1 -0
- package/src/components/Modal/Modal.test.tsx +1 -0
- package/src/components/NumberInput/NumberInput.test.tsx +1 -0
- package/src/components/Pagination/Pagination.test.tsx +1 -0
- package/src/components/Panel/Panel.test.tsx +1 -0
- package/src/components/Popover/Popover.test.tsx +1 -0
- package/src/components/Radio/Radio.test.tsx +1 -0
- package/src/components/ReadOnlyField/ReadOnlyField.test.tsx +1 -0
- package/src/components/SegmentedControl/SegmentedControl.test.tsx +1 -0
- package/src/components/Slider/Slider.test.tsx +1 -0
- package/src/components/Stack/Stack.stories.tsx +9 -9
- package/src/components/Stack/Stack.test.tsx +1 -0
- package/src/components/Stack/Stack.tsx +15 -14
- package/src/components/Stack/USAGE.md +1 -1
- package/src/components/Stepper/Stepper.test.tsx +1 -0
- package/src/components/Switch/Switch.stories.tsx +1 -1
- package/src/components/Switch/Switch.test.tsx +1 -0
- package/src/components/Table/Table.test.tsx +1 -0
- package/src/components/Tabs/Tabs.test.tsx +1 -0
- package/src/components/Text/Text.stories.tsx +3 -16
- package/src/components/Text/Text.test.tsx +1 -0
- package/src/components/TextArea/TextArea.test.tsx +1 -0
- package/src/components/TextField/TextField.test.tsx +1 -0
- package/src/components/TimePicker/TimePicker.test.tsx +1 -0
- package/src/components/Timeline/Timeline.test.tsx +1 -0
- package/src/components/Title/Title.stories.tsx +3 -16
- package/src/components/Title/Title.test.tsx +1 -0
- package/src/components/Toast/Toast.test.tsx +1 -0
- package/src/components/Tooltip/Tooltip.test.tsx +1 -0
- package/src/components/TransferList/TransferList.test.tsx +1 -0
- package/src/components/Tree/Tree.test.tsx +1 -0
- package/src/components/Typography/Typography.test.tsx +1 -0
- package/src/utils/filterStylingProps.test.ts +85 -0
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Grid layout wrapper.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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:
|
|
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"
|
|
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" | "
|
|
129
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
147
|
-
typeof
|
|
148
|
-
? SPACING_MAP[
|
|
149
|
-
:
|
|
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
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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" | "
|
|
179
|
-
|
|
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[
|
|
123
|
+
? VISIBLE_FROM_CLASS[visibleFrom]
|
|
203
124
|
: hiddenFrom
|
|
204
|
-
? HIDDEN_FROM_CLASS[
|
|
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
|
|
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
|
-
|
|
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
|
-
- **`
|
|
8
|
-
- **`
|
|
9
|
-
- **`offset
|
|
10
|
-
-
|
|
11
|
-
- **`
|
|
12
|
-
- **`
|
|
13
|
-
- **`
|
|
14
|
-
- **`
|
|
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`
|
|
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
|
|
24
|
-
<Grid.Col
|
|
25
|
-
<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
|
-
|
|
48
|
-
|
|
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
|
|
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
|
-
|
|
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"> &
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
spacing: "rec-default",
|
|
23
|
+
alignItems: "stretch",
|
|
24
|
+
justifyContent: "flex-start",
|
|
25
25
|
},
|
|
26
26
|
argTypes: {
|
|
27
|
-
|
|
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: "
|
|
43
|
+
description: "Space between elements",
|
|
44
44
|
},
|
|
45
|
-
|
|
45
|
+
alignItems: {
|
|
46
46
|
control: "select",
|
|
47
47
|
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
48
48
|
description: "Align-items property",
|
|
49
49
|
},
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
23
|
+
{ children, spacing = "rec-default", ...rest },
|
|
21
24
|
ref,
|
|
22
25
|
) {
|
|
23
26
|
const safeProps = filterSxProp(rest as Record<string, unknown>);
|
|
24
|
-
const
|
|
25
|
-
typeof
|
|
26
|
-
? SPACING_MAP[
|
|
27
|
-
:
|
|
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={
|
|
34
|
-
alignItems={align}
|
|
35
|
-
justifyContent={justify}
|
|
35
|
+
{...(safeProps as unknown as MUIStackProps)}
|
|
36
|
+
spacing={resolvedSpacing}
|
|
36
37
|
>
|
|
37
38
|
{children}
|
|
38
39
|
</MUIStack>
|
|
@@ -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
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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.
|