@recursica/mui-adapter 0.2.0 → 0.4.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.
- package/CHANGELOG.md +12 -0
- package/dist/mui-adapter.cjs +1 -1
- package/dist/mui-adapter.cjs.map +1 -1
- package/dist/mui-adapter.css +1 -1
- package/dist/mui-adapter.js +286 -91
- package/dist/mui-adapter.js.map +1 -1
- package/dist/src/components/Box/Box.d.ts +2 -3
- package/dist/src/components/Button/Button.d.ts +40 -2
- package/dist/src/components/Container/Container.d.ts +8 -2
- package/dist/src/components/Flex/Flex.d.ts +25 -2
- package/dist/src/components/Group/Group.d.ts +10 -2
- package/dist/src/components/Link/Link.d.ts +13 -2
- package/dist/src/components/Loader/Loader.d.ts +9 -2
- package/dist/src/components/Stack/Stack.d.ts +8 -2
- package/dist/src/components/Text/Text.d.ts +18 -2
- package/dist/src/components/Title/Title.d.ts +17 -2
- package/dist/src/components/Typography/Typography.d.ts +27 -0
- package/dist/src/utils/filterStylingProps.d.ts +3 -0
- package/package.json +2 -1
- package/src/Introduction.stories.tsx +113 -110
- package/src/OverStyling.tsx +18 -23
- package/src/Version.tsx +14 -21
- package/src/components/Accordion/Accordion.stories.tsx +19 -0
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +19 -0
- package/src/components/Avatar/Avatar.stories.tsx +19 -0
- package/src/components/Badge/Badge.stories.tsx +19 -0
- package/src/components/Box/Box.stories.tsx +19 -10
- package/src/components/Box/Box.tsx +11 -14
- package/src/components/Box/IMPLEMENTATION_NOTES.md +5 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +19 -0
- package/src/components/Button/BUTTON_IMPLEMENTATION_NOTES.md +33 -0
- package/src/components/Button/Button.module.css +343 -0
- package/src/components/Button/Button.stories.tsx +181 -5
- package/src/components/Button/Button.tsx +141 -5
- package/src/components/Card/Card.stories.tsx +19 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +19 -0
- package/src/components/Chip/Chip.stories.tsx +19 -0
- package/src/components/Container/Container.stories.tsx +19 -0
- package/src/components/Container/Container.tsx +56 -5
- package/src/components/Container/IMPLEMENTATION_NOTES.md +5 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +19 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +19 -0
- package/src/components/FileInput/FileInput.stories.tsx +19 -0
- package/src/components/FileUpload/FileUpload.stories.tsx +19 -0
- package/src/components/Flex/Flex.stories.tsx +19 -0
- package/src/components/Flex/Flex.tsx +77 -5
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +19 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +19 -0
- package/src/components/Group/Group.stories.tsx +133 -5
- package/src/components/Group/Group.tsx +57 -5
- package/src/components/HoverCard/HoverCard.stories.tsx +19 -0
- package/src/components/Label/Label.stories.tsx +19 -0
- package/src/components/Link/Link.module.css +133 -0
- package/src/components/Link/Link.stories.tsx +52 -4
- package/src/components/Link/Link.tsx +47 -5
- package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/Loader/Loader.module.css +166 -0
- package/src/components/Loader/Loader.stories.tsx +93 -6
- package/src/components/Loader/Loader.tsx +69 -5
- package/src/components/Menu/Menu.stories.tsx +19 -0
- package/src/components/Modal/Modal.stories.tsx +19 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +19 -0
- package/src/components/Pagination/Pagination.stories.tsx +19 -0
- package/src/components/Panel/Panel.stories.tsx +19 -0
- package/src/components/Radio/Radio.stories.tsx +19 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +19 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +19 -0
- package/src/components/Slider/Slider.stories.tsx +19 -0
- package/src/components/Stack/Stack.stories.tsx +118 -5
- package/src/components/Stack/Stack.tsx +37 -5
- package/src/components/Stepper/Stepper.stories.tsx +19 -0
- package/src/components/Switch/Switch.stories.tsx +19 -0
- package/src/components/Table/Table.stories.tsx +19 -0
- package/src/components/Tabs/Tabs.stories.tsx +19 -0
- package/src/components/Text/Text.stories.tsx +87 -3
- package/src/components/Text/Text.tsx +27 -4
- package/src/components/TextArea/TextArea.stories.tsx +19 -0
- package/src/components/TextField/TextField.stories.tsx +19 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +19 -0
- package/src/components/Timeline/Timeline.stories.tsx +19 -0
- package/src/components/Title/Title.stories.tsx +68 -3
- package/src/components/Title/Title.tsx +29 -5
- package/src/components/Toast/Toast.stories.tsx +19 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +19 -0
- package/src/components/TransferList/TransferList.stories.tsx +19 -0
- package/src/components/Typography/Typography.tsx +42 -0
- package/src/utils/ColorSchemeWrapper.tsx +1 -5
- package/src/utils/filterStylingProps.ts +13 -1
|
@@ -1,16 +1,192 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
3
|
import { Button } from "./Button";
|
|
3
|
-
import {
|
|
4
|
+
import { Layer } from "@recursica/adapter-common";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
type ButtonStoryProps = React.ComponentProps<typeof Button>;
|
|
7
|
+
|
|
8
|
+
const meta: Meta<ButtonStoryProps> = {
|
|
9
|
+
title: "UI-Kit/Button",
|
|
7
10
|
component: Button,
|
|
8
11
|
tags: ["autodocs"],
|
|
12
|
+
argTypes: {
|
|
13
|
+
variant: {
|
|
14
|
+
control: "select",
|
|
15
|
+
options: ["solid", "outline", "text"],
|
|
16
|
+
description: "The visual variant of the button",
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
control: "radio",
|
|
20
|
+
options: ["default", "small"],
|
|
21
|
+
description: "The size of the button",
|
|
22
|
+
},
|
|
23
|
+
loading: {
|
|
24
|
+
control: "boolean",
|
|
25
|
+
description: "Sets the button to a loading state",
|
|
26
|
+
},
|
|
27
|
+
useRecursicaLoader: {
|
|
28
|
+
control: "boolean",
|
|
29
|
+
description:
|
|
30
|
+
"Use the Recursica Loader component instead of the default Mantine loader",
|
|
31
|
+
},
|
|
32
|
+
loaderVariant: {
|
|
33
|
+
control: "select",
|
|
34
|
+
options: ["oval", "bars", "dots"],
|
|
35
|
+
description: "The visual variant of the Recursica Loader",
|
|
36
|
+
},
|
|
37
|
+
loaderSize: {
|
|
38
|
+
control: "select",
|
|
39
|
+
options: [undefined, "sm", "md", "lg", "small", "default", "large"],
|
|
40
|
+
description: "The size variant for the loader",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
args: {
|
|
44
|
+
useRecursicaLoader: true,
|
|
45
|
+
loaderVariant: "oval",
|
|
46
|
+
loaderSize: undefined,
|
|
47
|
+
},
|
|
48
|
+
parameters: {
|
|
49
|
+
controls: {
|
|
50
|
+
include: [
|
|
51
|
+
"layer",
|
|
52
|
+
"withLayer",
|
|
53
|
+
"variant",
|
|
54
|
+
"size",
|
|
55
|
+
"children",
|
|
56
|
+
"component",
|
|
57
|
+
"icon",
|
|
58
|
+
"disabled",
|
|
59
|
+
"href",
|
|
60
|
+
"onClick",
|
|
61
|
+
"onChange",
|
|
62
|
+
"value",
|
|
63
|
+
"checked",
|
|
64
|
+
"loading",
|
|
65
|
+
"useRecursicaLoader",
|
|
66
|
+
"loaderVariant",
|
|
67
|
+
"loaderSize",
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
},
|
|
9
71
|
};
|
|
10
72
|
|
|
11
73
|
export default meta;
|
|
12
|
-
|
|
74
|
+
|
|
75
|
+
type Story = StoryObj<ButtonStoryProps>;
|
|
13
76
|
|
|
14
77
|
export const Default: Story = {
|
|
15
|
-
|
|
78
|
+
args: {
|
|
79
|
+
children: "Explore Button",
|
|
80
|
+
variant: "solid",
|
|
81
|
+
size: "default",
|
|
82
|
+
disabled: false,
|
|
83
|
+
},
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
85
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
86
|
+
return <Button {...args} />;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const SolidDefault: Story = {
|
|
91
|
+
args: {
|
|
92
|
+
children: "Solid Default",
|
|
93
|
+
variant: "solid",
|
|
94
|
+
size: "default",
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const OutlineSmall: Story = {
|
|
99
|
+
args: {
|
|
100
|
+
children: "Outline Small",
|
|
101
|
+
variant: "outline",
|
|
102
|
+
size: "small",
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const TextWithIcon: Story = {
|
|
107
|
+
args: {
|
|
108
|
+
children: "Text With Icon",
|
|
109
|
+
variant: "text",
|
|
110
|
+
size: "default",
|
|
111
|
+
icon: (
|
|
112
|
+
<svg
|
|
113
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
114
|
+
width="24"
|
|
115
|
+
height="24"
|
|
116
|
+
viewBox="0 0 24 24"
|
|
117
|
+
fill="none"
|
|
118
|
+
stroke="currentColor"
|
|
119
|
+
strokeWidth="2"
|
|
120
|
+
strokeLinecap="round"
|
|
121
|
+
strokeLinejoin="round"
|
|
122
|
+
>
|
|
123
|
+
<circle cx="11" cy="11" r="8"></circle>
|
|
124
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
125
|
+
</svg>
|
|
126
|
+
),
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const LayerOneSolid: Story = {
|
|
131
|
+
args: {
|
|
132
|
+
children: "Layer 1 Solid",
|
|
133
|
+
variant: "solid",
|
|
134
|
+
size: "default",
|
|
135
|
+
},
|
|
136
|
+
render: (args: ButtonStoryProps) => (
|
|
137
|
+
<Layer layer={1} style={{ padding: "24px" }}>
|
|
138
|
+
<Button {...args} />
|
|
139
|
+
</Layer>
|
|
140
|
+
),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const DisabledSolid: Story = {
|
|
144
|
+
args: {
|
|
145
|
+
children: "Disabled Solid",
|
|
146
|
+
variant: "solid",
|
|
147
|
+
size: "default",
|
|
148
|
+
disabled: true,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export const PolymorphicAsLink: Story = {
|
|
153
|
+
args: {
|
|
154
|
+
children: "Button as Link",
|
|
155
|
+
variant: "solid",
|
|
156
|
+
size: "default",
|
|
157
|
+
component: "a",
|
|
158
|
+
href: "https://example.com",
|
|
159
|
+
target: "_blank",
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export const TruncatedLabel: Story = {
|
|
164
|
+
args: {
|
|
165
|
+
children:
|
|
166
|
+
"This is an exceptionally long button label designed to demonstrate how the component handles text overflow by applying an ellipsis rather than breaking the layout or wrapping to multiple lines.",
|
|
167
|
+
variant: "solid",
|
|
168
|
+
size: "default",
|
|
169
|
+
},
|
|
170
|
+
render: (args: ButtonStoryProps) => (
|
|
171
|
+
<div style={{ maxWidth: "250px" }}>
|
|
172
|
+
<Button {...args} />
|
|
173
|
+
</div>
|
|
174
|
+
),
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export const Loading: Story = {
|
|
178
|
+
args: {
|
|
179
|
+
children: "Saving Changes",
|
|
180
|
+
variant: "solid",
|
|
181
|
+
size: "default",
|
|
182
|
+
loading: true,
|
|
183
|
+
},
|
|
184
|
+
parameters: {
|
|
185
|
+
docs: {
|
|
186
|
+
description: {
|
|
187
|
+
story:
|
|
188
|
+
"When `loading={true}` is applied, the Button injects the Recursica `<Loader />` component. Per Recursica design rules, placing a Button in a loading state automatically forces the `disabled={true}` state on the underlying element. This ensures the button immediately receives the brand theme disabled opacities without relying solely on semantic logic.",
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
},
|
|
16
192
|
};
|
|
@@ -1,7 +1,143 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import { Loader } from "../Loader/Loader";
|
|
3
|
+
import type { RecursicaLoaderProps } from "../Loader/Loader";
|
|
4
|
+
import {
|
|
5
|
+
Button as MuiButton,
|
|
6
|
+
type ButtonProps as MuiButtonProps,
|
|
7
|
+
} from "@mui/material";
|
|
8
|
+
import {
|
|
9
|
+
filterStylingProps,
|
|
10
|
+
type RecursicaOverStyled,
|
|
11
|
+
} from "../../utils/filterStylingProps";
|
|
12
|
+
import styles from "./Button.module.css";
|
|
2
13
|
|
|
3
|
-
export
|
|
14
|
+
export interface RecursicaButtonProps {
|
|
15
|
+
variant?: "solid" | "outline" | "text";
|
|
16
|
+
size?: "default" | "small";
|
|
17
|
+
icon?: React.ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* For polymorphic support (e.g., `component="a"`), native to MUI.
|
|
20
|
+
*/
|
|
21
|
+
component?: React.ElementType;
|
|
22
|
+
/** Which Recursica Loader variant to use */
|
|
23
|
+
loaderVariant?: RecursicaLoaderProps["variant"];
|
|
24
|
+
/** The size variant for the loader */
|
|
25
|
+
loaderSize?: RecursicaLoaderProps["size"];
|
|
26
|
+
/** Whether to use the Recursica loader or fallback to the Mantine loader */
|
|
27
|
+
useRecursicaLoader?: boolean;
|
|
28
|
+
}
|
|
4
29
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
30
|
+
export type ButtonProps = RecursicaOverStyled<
|
|
31
|
+
Omit<MuiButtonProps, "variant" | "size" | "color" | "fullWidth"> &
|
|
32
|
+
RecursicaButtonProps
|
|
33
|
+
>;
|
|
34
|
+
|
|
35
|
+
function hasVisibleChildren(children: React.ReactNode): boolean {
|
|
36
|
+
if (children == null || children === "") return false;
|
|
37
|
+
if (typeof children === "string") return children.trim() !== "";
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Recursica Button component wrapping MUI's Button.
|
|
43
|
+
*
|
|
44
|
+
* Supports polymorphism via the `component` prop for custom element rendering.
|
|
45
|
+
* This is particularly useful when you need a button that behaves as a hyperlink (rendering an `<a>` tag)
|
|
46
|
+
* or integrates with a routing library (e.g., `react-router-dom` or Next.js), while preserving full visual styling.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* // Renders as an <a> tag natively
|
|
51
|
+
* <Button component="a" href="/dashboard" target="_blank">Navigate</Button>
|
|
52
|
+
*
|
|
53
|
+
* // Renders using a custom router link
|
|
54
|
+
* <Button component={Link} to="/home">Home</Button>
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
58
|
+
function Button(
|
|
59
|
+
{
|
|
60
|
+
variant = "solid",
|
|
61
|
+
size = "default",
|
|
62
|
+
icon,
|
|
63
|
+
children,
|
|
64
|
+
overStyled = false,
|
|
65
|
+
loaderVariant = "oval",
|
|
66
|
+
loaderSize,
|
|
67
|
+
useRecursicaLoader = true,
|
|
68
|
+
...rest
|
|
69
|
+
},
|
|
70
|
+
ref,
|
|
71
|
+
) {
|
|
72
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
73
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
74
|
+
|
|
75
|
+
// Explicitly delete blocked semantic expansion dimension props that MUI uses natively
|
|
76
|
+
delete restRecord["fullWidth"];
|
|
77
|
+
delete restRecord["color"]; // Recursica handles colors internally via tokens
|
|
78
|
+
|
|
79
|
+
const hasStartIcon = !!icon || !!restRecord["startIcon"];
|
|
80
|
+
const hasEndIcon = !!restRecord["endIcon"];
|
|
81
|
+
const isIconOnly =
|
|
82
|
+
(hasStartIcon || hasEndIcon) && !hasVisibleChildren(children);
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
typeof process !== "undefined" &&
|
|
86
|
+
process.env.NODE_ENV !== "production" &&
|
|
87
|
+
isIconOnly &&
|
|
88
|
+
!restRecord["aria-label"]
|
|
89
|
+
) {
|
|
90
|
+
console.warn(
|
|
91
|
+
'[Recursica Button] Icon-only buttons must provide an accessible name. Pass aria-label (e.g. aria-label="Submit").',
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
96
|
+
const finalClass = classNameProp
|
|
97
|
+
? `${styles.root} ${classNameProp}`
|
|
98
|
+
: styles.root;
|
|
99
|
+
|
|
100
|
+
// We don't map Recursica variant/size to MUI's because we want to completely disable MUI's native
|
|
101
|
+
// variant logic (e.g., elevation, shadows) and style everything strictly through our CSS Modules.
|
|
102
|
+
// However, Mui Button requires some string, but we can just leave it as standard or ignore since
|
|
103
|
+
// our CSS resets its properties anyway, but to be clean we just don't pass variant to MUI.
|
|
104
|
+
|
|
105
|
+
const resolvedLoaderSize =
|
|
106
|
+
loaderSize ?? (size === "small" ? "small" : "default");
|
|
107
|
+
|
|
108
|
+
let loadingIndicator = restRecord.loadingIndicator as React.ReactNode;
|
|
109
|
+
if (useRecursicaLoader) {
|
|
110
|
+
loadingIndicator = (
|
|
111
|
+
<Loader variant={loaderVariant} size={resolvedLoaderSize} />
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<MuiButton
|
|
117
|
+
ref={ref}
|
|
118
|
+
disableRipple
|
|
119
|
+
disableElevation
|
|
120
|
+
className={finalClass}
|
|
121
|
+
loading={!!restRecord.loading}
|
|
122
|
+
loadingIndicator={loadingIndicator}
|
|
123
|
+
startIcon={
|
|
124
|
+
icon != null ? (
|
|
125
|
+
<span className={styles.iconWrapper} aria-hidden>
|
|
126
|
+
{icon}
|
|
127
|
+
</span>
|
|
128
|
+
) : undefined
|
|
129
|
+
}
|
|
130
|
+
data-variant={variant}
|
|
131
|
+
data-size={size}
|
|
132
|
+
{...(isIconOnly ? { "data-icon-only": "" } : {})}
|
|
133
|
+
{...(restRecord.loading ? { "data-loading": "true" } : {})}
|
|
134
|
+
{...sanitizedProps}
|
|
135
|
+
disabled={!!restRecord.disabled || !!restRecord.loading}
|
|
136
|
+
>
|
|
137
|
+
<span className={styles.labelText}>{children}</span>
|
|
138
|
+
</MuiButton>
|
|
139
|
+
);
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
Button.displayName = "Button";
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof Card> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 Card",
|
|
7
7
|
component: Card,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof Checkbox> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 Checkbox",
|
|
7
7
|
component: Checkbox,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof Chip> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 Chip",
|
|
7
7
|
component: Chip,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof Container> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 Container",
|
|
7
7
|
component: Container,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -1,7 +1,58 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Container layout wrapper.
|
|
3
|
+
*
|
|
4
|
+
* NOTE: As a foundational structural boundary, the Container component DOES NOT use
|
|
5
|
+
* the `RecursicaOverStyled` gatekeeper. Furthermore, unlike other primitive layouts
|
|
6
|
+
* (Stack, Group, Flex), Container explicitly ALLOWS the `sx` prop as an escape hatch
|
|
7
|
+
* for advanced layout positioning.
|
|
8
|
+
*/
|
|
9
|
+
import React, { forwardRef } from "react";
|
|
10
|
+
import {
|
|
11
|
+
Container as MUIContainer,
|
|
12
|
+
type ContainerProps as MUIContainerProps,
|
|
13
|
+
} from "@mui/material";
|
|
14
|
+
import { type RecursicaSpacing } from "../../utils/filterStylingProps";
|
|
2
15
|
|
|
3
|
-
export
|
|
16
|
+
export interface RecursicaContainerProps {
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
size?:
|
|
19
|
+
| "xs"
|
|
20
|
+
| "sm"
|
|
21
|
+
| "md"
|
|
22
|
+
| "lg"
|
|
23
|
+
| "xl"
|
|
24
|
+
| RecursicaSpacing
|
|
25
|
+
| (string & {})
|
|
26
|
+
| number;
|
|
27
|
+
}
|
|
4
28
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
29
|
+
export type ContainerProps = Omit<MUIContainerProps, "maxWidth"> &
|
|
30
|
+
RecursicaContainerProps;
|
|
31
|
+
|
|
32
|
+
export const Container = forwardRef<HTMLDivElement, ContainerProps>(
|
|
33
|
+
function Container({ children, size, ...rest }, ref) {
|
|
34
|
+
const mapSize: Record<string, "xs" | "sm" | "md" | "lg" | "xl"> = {
|
|
35
|
+
"rec-sm": "sm",
|
|
36
|
+
"rec-default": "md",
|
|
37
|
+
"rec-md": "md",
|
|
38
|
+
"rec-lg": "lg",
|
|
39
|
+
"rec-xl": "xl",
|
|
40
|
+
"rec-2xl": "xl",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const resolvedSize =
|
|
44
|
+
typeof size === "string" && mapSize[size] ? mapSize[size] : size;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<MUIContainer
|
|
48
|
+
ref={ref}
|
|
49
|
+
maxWidth={resolvedSize as MUIContainerProps["maxWidth"]}
|
|
50
|
+
{...rest}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</MUIContainer>
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
Container.displayName = "Container";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Container Implementation Notes
|
|
2
|
+
|
|
3
|
+
## `sx` Prop Exemption
|
|
4
|
+
|
|
5
|
+
By design, the `Container` component explicitly allows the `sx` prop to pass through to the underlying MUI `Container`. Unlike standard UI kit components (which use the `RecursicaOverStyled` gatekeeper) or flex layout primitives (which strip `sx` via `OmitSx` and `filterSxProp`), `Container` acts as a structural boundary where advanced, one-off positioning adjustments may be required by the consuming application.
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof DatePicker> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 DatePicker",
|
|
7
7
|
component: DatePicker,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof Dropdown> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 Dropdown",
|
|
7
7
|
component: Dropdown,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof FileInput> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 FileInput",
|
|
7
7
|
component: FileInput,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof FileUpload> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 FileUpload",
|
|
7
7
|
component: FileUpload,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|
|
@@ -6,6 +6,25 @@ const meta: Meta<typeof Flex> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 Flex",
|
|
7
7
|
component: Flex,
|
|
8
8
|
tags: ["autodocs"],
|
|
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
|
+
],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
9
28
|
};
|
|
10
29
|
|
|
11
30
|
export default meta;
|