@recursica/mui-adapter 0.34.0 → 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 +27 -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 +9 -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.stories.tsx +25 -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.module.css +103 -1
- package/src/components/Modal/Modal.stories.tsx +28 -2
- 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
|
@@ -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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Timeline component tests. Add tests here if/when needed.
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { Title } from "./Title";
|
|
3
|
-
import { Layer } from "@recursica/adapter-common";
|
|
4
3
|
|
|
5
4
|
const meta: Meta<typeof Title> = {
|
|
6
5
|
title: "UI-Kit/Title",
|
|
@@ -33,31 +32,19 @@ export const Default: Story = {
|
|
|
33
32
|
order: 1,
|
|
34
33
|
children: "Semantic H1 Document Boundary",
|
|
35
34
|
},
|
|
36
|
-
render: ({ ...args }) =>
|
|
37
|
-
<Layer layer={0} style={{ padding: "48px" }}>
|
|
38
|
-
<Title {...args} />
|
|
39
|
-
</Layer>
|
|
40
|
-
),
|
|
35
|
+
render: ({ ...args }) => <Title {...args} />,
|
|
41
36
|
};
|
|
42
37
|
|
|
43
38
|
export const StaticVariations: Story = {
|
|
44
39
|
args: {},
|
|
45
40
|
render: () => (
|
|
46
|
-
<
|
|
47
|
-
layer={0}
|
|
48
|
-
style={{
|
|
49
|
-
padding: "48px",
|
|
50
|
-
display: "flex",
|
|
51
|
-
flexDirection: "column",
|
|
52
|
-
gap: "24px",
|
|
53
|
-
}}
|
|
54
|
-
>
|
|
41
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
55
42
|
<Title order={1}>H1 Title</Title>
|
|
56
43
|
<Title order={2}>H2 Title</Title>
|
|
57
44
|
<Title order={3}>H3 Title</Title>
|
|
58
45
|
<Title order={4}>H4 Title</Title>
|
|
59
46
|
<Title order={5}>H5 Title</Title>
|
|
60
47
|
<Title order={6}>H6 Title</Title>
|
|
61
|
-
</
|
|
48
|
+
</div>
|
|
62
49
|
),
|
|
63
50
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Title component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Toast component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Tooltip component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future TransferList component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Tree component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Typography component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
BLOCKED_STYLING_KEYS,
|
|
4
|
+
SPACING_MAP,
|
|
5
|
+
filterStylingProps,
|
|
6
|
+
filterSxProp,
|
|
7
|
+
} from "./filterStylingProps";
|
|
8
|
+
|
|
9
|
+
describe("filterStylingProps", () => {
|
|
10
|
+
it("strips every blocked styling key by default", () => {
|
|
11
|
+
const props = Object.fromEntries(
|
|
12
|
+
BLOCKED_STYLING_KEYS.map((key) => [key, "should-be-removed"]),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const sanitized = filterStylingProps(props);
|
|
16
|
+
|
|
17
|
+
for (const key of BLOCKED_STYLING_KEYS) {
|
|
18
|
+
expect(sanitized).not.toHaveProperty(key);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("keeps props that aren't blocked styling keys", () => {
|
|
23
|
+
const sanitized = filterStylingProps({
|
|
24
|
+
disabled: true,
|
|
25
|
+
"aria-label": "Submit",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(sanitized).toEqual({ disabled: true, "aria-label": "Submit" });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("keeps layout props (e.g. margin) untouched when not a rec- token", () => {
|
|
32
|
+
const sanitized = filterStylingProps({ m: "16px" });
|
|
33
|
+
|
|
34
|
+
expect(sanitized).toEqual({ m: "16px" });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("maps rec- spacing tokens on layout props to their CSS variable", () => {
|
|
38
|
+
const sanitized = filterStylingProps({ m: "rec-lg", gap: "rec-sm" });
|
|
39
|
+
|
|
40
|
+
expect(sanitized).toEqual({
|
|
41
|
+
m: SPACING_MAP["rec-lg"],
|
|
42
|
+
gap: SPACING_MAP["rec-sm"],
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("does not map rec- tokens on props that aren't layout props", () => {
|
|
47
|
+
const sanitized = filterStylingProps({ "data-testid": "rec-lg" });
|
|
48
|
+
|
|
49
|
+
expect(sanitized).toEqual({ "data-testid": "rec-lg" });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("leaves an unrecognized rec- value alone", () => {
|
|
53
|
+
const sanitized = filterStylingProps({ m: "rec-not-a-real-token" });
|
|
54
|
+
|
|
55
|
+
expect(sanitized).toEqual({ m: "rec-not-a-real-token" });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("bypasses all filtering when overStyled is true", () => {
|
|
59
|
+
const props = { className: "custom", sx: { color: "red" }, m: "rec-lg" };
|
|
60
|
+
|
|
61
|
+
expect(filterStylingProps(props, true)).toEqual(props);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("does not mutate the input props object", () => {
|
|
65
|
+
const props = { className: "custom", m: "rec-lg" };
|
|
66
|
+
|
|
67
|
+
filterStylingProps(props);
|
|
68
|
+
|
|
69
|
+
expect(props).toEqual({ className: "custom", m: "rec-lg" });
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("filterSxProp", () => {
|
|
74
|
+
it("removes only the sx prop", () => {
|
|
75
|
+
const sanitized = filterSxProp({ sx: { color: "red" }, disabled: true });
|
|
76
|
+
|
|
77
|
+
expect(sanitized).toEqual({ disabled: true });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("is a no-op when sx isn't present", () => {
|
|
81
|
+
const props = { disabled: true };
|
|
82
|
+
|
|
83
|
+
expect(filterSxProp(props)).toEqual(props);
|
|
84
|
+
});
|
|
85
|
+
});
|