@recursica/mui-adapter 0.9.1 → 0.11.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 +22 -0
- package/dist/mui-adapter.cjs +30 -20
- package/dist/mui-adapter.cjs.map +1 -1
- package/dist/mui-adapter.css +1 -1
- package/dist/mui-adapter.js +2410 -2085
- package/dist/mui-adapter.js.map +1 -1
- package/dist/src/components/Accordion/Accordion.d.ts +43 -10
- package/dist/src/components/Autocomplete/Autocomplete.d.ts +13 -2
- package/dist/src/components/Avatar/Avatar.d.ts +16 -1
- package/dist/src/components/Badge/Badge.d.ts +16 -1
- package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +13 -2
- package/dist/src/components/Button/Button.d.ts +13 -2
- package/dist/src/components/Card/Card.d.ts +45 -2
- package/dist/src/components/Checkbox/CheckboxGroup.d.ts +14 -3
- package/dist/src/components/Chip/Chip.d.ts +13 -2
- package/dist/src/components/Container/Container.d.ts +3 -3
- package/dist/src/components/Dropdown/Dropdown.d.ts +14 -3
- package/dist/src/components/Flex/Flex.d.ts +3 -4
- package/dist/src/components/Group/Group.d.ts +3 -4
- package/dist/src/components/Link/Link.d.ts +14 -4
- package/dist/src/components/Menu/Menu.d.ts +37 -8
- package/dist/src/components/Modal/Modal.d.ts +51 -11
- package/dist/src/components/NumberInput/NumberInput.d.ts +13 -2
- package/dist/src/components/Pagination/Pagination.d.ts +13 -2
- package/dist/src/components/Panel/Panel.d.ts +6 -6
- package/dist/src/components/Radio/index.d.ts +1 -0
- package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +15 -4
- package/dist/src/components/Slider/Slider.d.ts +13 -2
- package/dist/src/components/Stack/Stack.d.ts +3 -4
- package/dist/src/components/Stepper/Stepper.d.ts +71 -16
- package/dist/src/components/Switch/Switch.d.ts +1 -1
- package/dist/src/components/Switch/SwitchGroup.d.ts +14 -3
- package/dist/src/components/Switch/index.d.ts +1 -0
- package/dist/src/components/Table/Table.d.ts +34 -3
- package/dist/src/components/Tabs/Tabs.d.ts +45 -8
- package/dist/src/components/Text/Text.d.ts +18 -3
- package/dist/src/components/TextArea/TextArea.d.ts +14 -3
- package/dist/src/components/TextField/TextField.d.ts +13 -2
- package/dist/src/components/Timeline/TimelineItem.d.ts +13 -2
- package/dist/src/components/Timeline/index.d.ts +1 -0
- package/dist/src/components/Title/Title.d.ts +18 -2
- package/dist/src/components/Toast/Toast.d.ts +13 -2
- package/dist/src/components/Typography/Typography.d.ts +14 -3
- package/dist/src/components/Typography/index.d.ts +1 -0
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/index.d.ts +85 -1
- package/dist/src/utils/filterStylingProps.d.ts +1 -1
- package/package.json +1 -1
- package/src/OverStyling.tsx +63 -2
- package/src/components/Accordion/Accordion.tsx +1 -0
- package/src/components/Autocomplete/Autocomplete.tsx +2 -0
- package/src/components/Avatar/Avatar.tsx +3 -3
- package/src/components/Badge/Badge.tsx +1 -1
- package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +15 -0
- package/src/components/Card/Card.module.css +1 -0
- package/src/components/Card/Card.tsx +30 -2
- package/src/components/Checkbox/Checkbox.tsx +6 -1
- package/src/components/Checkbox/CheckboxGroup.tsx +6 -2
- package/src/components/Container/Container.tsx +5 -3
- package/src/components/Dropdown/Dropdown.tsx +10 -11
- package/src/components/Flex/Flex.tsx +5 -2
- package/src/components/Group/Group.tsx +4 -3
- package/src/components/HoverCard/HoverCard.tsx +7 -4
- package/src/components/Link/Link.tsx +1 -1
- package/src/components/Menu/Menu.stories.tsx +14 -8
- package/src/components/Modal/Modal.tsx +11 -4
- package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +64 -0
- package/src/components/Panel/Panel.stories.tsx +9 -9
- package/src/components/Panel/Panel.tsx +14 -9
- package/src/components/Radio/Radio.tsx +1 -0
- package/src/components/Radio/index.ts +1 -0
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +1 -1
- package/src/components/SegmentedControl/SegmentedControl.tsx +5 -1
- package/src/components/Slider/Slider.tsx +12 -4
- package/src/components/Stack/Stack.tsx +4 -3
- package/src/components/Stepper/Stepper.tsx +6 -1
- package/src/components/Switch/Switch.tsx +2 -1
- package/src/components/Switch/SwitchGroup.tsx +5 -1
- package/src/components/Switch/index.ts +1 -0
- package/src/components/Table/Table.module.css +7 -0
- package/src/components/Table/Table.stories.tsx +35 -3
- package/src/components/Table/Table.tsx +61 -5
- package/src/components/Tabs/Tabs.tsx +5 -1
- package/src/components/Text/Text.tsx +5 -2
- package/src/components/TextArea/TextArea.tsx +11 -10
- package/src/components/TextField/TextField.tsx +2 -0
- package/src/components/Timeline/index.ts +1 -0
- package/src/components/Title/Title.tsx +4 -1
- package/src/components/Typography/index.ts +1 -0
- package/src/components/index.ts +1 -0
- package/src/index.ts +180 -1
- package/src/utils/filterStylingProps.ts +1 -0
|
@@ -8,20 +8,31 @@ export type TypographyProps = RecursicaOverStyled<Omit<MuiTypographyProps, "vari
|
|
|
8
8
|
typographyClass: string;
|
|
9
9
|
component?: React.ElementType;
|
|
10
10
|
}>;
|
|
11
|
-
export declare const Typography: React.ForwardRefExoticComponent<(Omit<Omit<Omit<MuiTypographyProps, "variant"> & {
|
|
11
|
+
export declare const Typography: React.ForwardRefExoticComponent<(Omit<Omit<import('@recursica/adapter-common').WithRecursicaSpacing<Omit<MuiTypographyProps, "variant"> & {
|
|
12
12
|
/**
|
|
13
13
|
* Internal typography class mapping
|
|
14
14
|
*/
|
|
15
15
|
typographyClass: string;
|
|
16
16
|
component?: React.ElementType;
|
|
17
|
-
}
|
|
17
|
+
}>, import('@recursica/adapter-common').BlockedStylingKeys> & import('@recursica/adapter-common').ForbiddenStyles & {
|
|
18
18
|
overStyled?: false | undefined;
|
|
19
|
-
}, "ref"> | Omit<Omit<MuiTypographyProps, "variant"> & {
|
|
19
|
+
}, "ref"> | Omit<Omit<Omit<MuiTypographyProps, "variant"> & {
|
|
20
20
|
/**
|
|
21
21
|
* Internal typography class mapping
|
|
22
22
|
*/
|
|
23
23
|
typographyClass: string;
|
|
24
24
|
component?: React.ElementType;
|
|
25
|
+
}, "m" | "my" | "mx" | "mt" | "mb" | "ml" | "mr" | "gap" | "rowGap" | "columnGap"> & {
|
|
26
|
+
m?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
27
|
+
mx?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
28
|
+
my?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
29
|
+
mt?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
30
|
+
mb?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
31
|
+
ml?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
32
|
+
mr?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
33
|
+
gap?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
34
|
+
rowGap?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
35
|
+
columnGap?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
25
36
|
} & {
|
|
26
37
|
overStyled: true;
|
|
27
38
|
}, "ref">) & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Typography';
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,2 +1,86 @@
|
|
|
1
|
-
|
|
1
|
+
import * as rawComponents from "./components";
|
|
2
2
|
export * from '@recursica/adapter-common';
|
|
3
|
+
export declare const Box: <C extends React.ElementType = "div">(props: rawComponents.BoxProps<C> & {
|
|
4
|
+
ref?: React.ForwardedRef<any>;
|
|
5
|
+
}) => React.ReactElement | null;
|
|
6
|
+
export declare const Flex: import('react').ForwardRefExoticComponent<Omit<rawComponents.FlexProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
|
|
7
|
+
export declare const Group: import('react').ForwardRefExoticComponent<Omit<rawComponents.GroupProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
|
|
8
|
+
export declare const Stack: import('react').ForwardRefExoticComponent<Omit<rawComponents.StackProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
|
|
9
|
+
export declare const Container: import('react').ForwardRefExoticComponent<Omit<rawComponents.ContainerProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
|
|
10
|
+
export declare const Typography: import('react').ForwardRefExoticComponent<(Omit<Omit<import('@recursica/adapter-common').WithRecursicaSpacing<Omit<import('@mui/material').TypographyProps, "variant"> & {
|
|
11
|
+
typographyClass: string;
|
|
12
|
+
component?: React.ElementType;
|
|
13
|
+
}>, import('@recursica/adapter-common').BlockedStylingKeys> & import('@recursica/adapter-common').ForbiddenStyles & {
|
|
14
|
+
overStyled?: false | undefined;
|
|
15
|
+
}, "ref"> | Omit<Omit<Omit<import('@mui/material').TypographyProps, "variant"> & {
|
|
16
|
+
typographyClass: string;
|
|
17
|
+
component?: React.ElementType;
|
|
18
|
+
}, "m" | "my" | "mx" | "mt" | "mb" | "ml" | "mr" | "gap" | "rowGap" | "columnGap"> & {
|
|
19
|
+
m?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
20
|
+
mx?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
21
|
+
my?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
22
|
+
mt?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
23
|
+
mb?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
24
|
+
ml?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
25
|
+
mr?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
26
|
+
gap?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
27
|
+
rowGap?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
28
|
+
columnGap?: string | number | import('@recursica/adapter-common').RecursicaSpacing;
|
|
29
|
+
} & {
|
|
30
|
+
overStyled: true;
|
|
31
|
+
}, "ref">) & import('react').RefAttributes<HTMLElement>>;
|
|
32
|
+
export declare const FileInput: import('react').FC<rawComponents.FileInputProps>;
|
|
33
|
+
export declare const FileUpload: import('react').FC<rawComponents.FileUploadProps>;
|
|
34
|
+
export declare const Accordion: typeof rawComponents.Accordion;
|
|
35
|
+
export declare const AccordionItem: typeof rawComponents.AccordionItem;
|
|
36
|
+
export declare const AccordionControl: typeof rawComponents.AccordionControl;
|
|
37
|
+
export declare const AccordionPanel: typeof rawComponents.AccordionPanel;
|
|
38
|
+
export declare const AssistiveElement: typeof rawComponents.AssistiveElement;
|
|
39
|
+
export declare const Autocomplete: typeof rawComponents.Autocomplete;
|
|
40
|
+
export declare const Avatar: typeof rawComponents.Avatar;
|
|
41
|
+
export declare const Badge: typeof rawComponents.Badge;
|
|
42
|
+
export declare const Breadcrumb: typeof rawComponents.Breadcrumb;
|
|
43
|
+
export declare const Button: typeof rawComponents.Button;
|
|
44
|
+
export declare const Card: typeof rawComponents.Card;
|
|
45
|
+
export declare const Checkbox: typeof rawComponents.Checkbox;
|
|
46
|
+
export declare const CheckboxGroup: typeof rawComponents.CheckboxGroup;
|
|
47
|
+
export declare const Chip: typeof rawComponents.Chip;
|
|
48
|
+
export declare const DatePicker: typeof rawComponents.DatePicker;
|
|
49
|
+
export declare const Dropdown: typeof rawComponents.Dropdown;
|
|
50
|
+
export declare const FormControlLayout: typeof rawComponents.FormControlLayout;
|
|
51
|
+
export declare const FormControlWrapper: typeof rawComponents.FormControlWrapper;
|
|
52
|
+
export declare const HoverCard: typeof rawComponents.HoverCard;
|
|
53
|
+
export declare const Label: typeof rawComponents.Label;
|
|
54
|
+
export declare const Link: typeof rawComponents.Link;
|
|
55
|
+
export declare const Loader: typeof rawComponents.Loader;
|
|
56
|
+
export declare const Menu: typeof rawComponents.Menu;
|
|
57
|
+
export declare const MenuItem: typeof rawComponents.MenuItem;
|
|
58
|
+
export declare const MenuDivider: typeof rawComponents.MenuDivider;
|
|
59
|
+
export declare const Modal: typeof rawComponents.Modal;
|
|
60
|
+
export declare const NumberInput: typeof rawComponents.NumberInput;
|
|
61
|
+
export declare const Pagination: typeof rawComponents.Pagination;
|
|
62
|
+
export declare const Panel: typeof rawComponents.Panel;
|
|
63
|
+
export declare const PanelFooter: typeof rawComponents.PanelFooter;
|
|
64
|
+
export declare const Radio: typeof rawComponents.Radio;
|
|
65
|
+
export declare const RadioGroup: typeof rawComponents.RadioGroup;
|
|
66
|
+
export declare const ReadOnlyField: typeof rawComponents.ReadOnlyField;
|
|
67
|
+
export declare const SegmentedControl: typeof rawComponents.SegmentedControl;
|
|
68
|
+
export declare const Slider: typeof rawComponents.Slider;
|
|
69
|
+
export declare const Stepper: typeof rawComponents.Stepper;
|
|
70
|
+
export declare const Switch: typeof rawComponents.Switch;
|
|
71
|
+
export declare const SwitchGroup: typeof rawComponents.SwitchGroup;
|
|
72
|
+
export declare const Table: typeof rawComponents.Table;
|
|
73
|
+
export declare const Tab: typeof rawComponents.Tab;
|
|
74
|
+
export declare const TabPanel: typeof rawComponents.TabPanel;
|
|
75
|
+
export declare const Tabs: typeof rawComponents.Tabs;
|
|
76
|
+
export declare const Text: typeof rawComponents.Text;
|
|
77
|
+
export declare const TextArea: typeof rawComponents.TextArea;
|
|
78
|
+
export declare const TextField: typeof rawComponents.TextField;
|
|
79
|
+
export declare const TimePicker: typeof rawComponents.TimePicker;
|
|
80
|
+
export declare const Timeline: typeof rawComponents.Timeline;
|
|
81
|
+
export declare const TimelineItem: typeof rawComponents.TimelineItem;
|
|
82
|
+
export declare const Title: typeof rawComponents.Title;
|
|
83
|
+
export declare const Toast: typeof rawComponents.Toast;
|
|
84
|
+
export declare const Tooltip: typeof rawComponents.Tooltip;
|
|
85
|
+
export declare const TransferList: typeof rawComponents.TransferList;
|
|
86
|
+
export type { RecursicaAutocompleteProps, RecursicaDropdownProps, RecursicaFormControlWrapperProps, RecursicaNumberInputProps, RecursicaSliderProps, RecursicaTextAreaProps, RecursicaTextFieldProps, RecursicaToastProps, } from './components';
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* @returns Sanitized component props safe for internal styling merging
|
|
23
23
|
*/
|
|
24
24
|
export declare const BLOCKED_STYLING_KEYS: readonly ["className", "classes", "style", "sx", "color", "bgcolor", "backgroundColor", "typography", "fontFamily", "fontSize", "fontWeight", "lineHeight", "letterSpacing", "textAlign", "border", "borderTop", "borderBottom", "borderLeft", "borderRight", "borderColor", "borderRadius", "boxShadow", "display", "position", "zIndex"];
|
|
25
|
-
export { type RecursicaSpacing, type RecursicaSize, type RecursicaOverStyled, type BlockedStylingKeys, type ForbiddenStyles, } from '@recursica/adapter-common';
|
|
25
|
+
export { type RecursicaSpacing, type RecursicaSize, type RecursicaOverStyled, type BlockedStylingKeys, type ForbiddenStyles, type WithRecursicaSpacing, } from '@recursica/adapter-common';
|
|
26
26
|
export declare const SPACING_MAP: Record<string, string>;
|
|
27
27
|
export type OmitSx<T> = Omit<T, "sx">;
|
|
28
28
|
export declare function filterSxProp<T extends Record<string, unknown>>(props: T): Omit<T, "sx">;
|
package/package.json
CHANGED
package/src/OverStyling.tsx
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import { Paper, Divider } from "@mui/material";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
Container,
|
|
4
|
+
Stack,
|
|
5
|
+
Box,
|
|
6
|
+
Text as RawText,
|
|
7
|
+
Title,
|
|
8
|
+
Switch as RawSwitch,
|
|
9
|
+
} from "./components";
|
|
10
|
+
import { Button as RawButton } from "./components/Button/Button";
|
|
11
|
+
import {
|
|
12
|
+
useGlobalOverStyled,
|
|
13
|
+
toggleGlobalOverStyled,
|
|
14
|
+
wrapComponent,
|
|
15
|
+
} from "@recursica/adapter-common";
|
|
16
|
+
|
|
17
|
+
const Button = wrapComponent(RawButton);
|
|
18
|
+
const Text = wrapComponent(RawText);
|
|
19
|
+
const Switch = wrapComponent(RawSwitch);
|
|
4
20
|
|
|
5
21
|
export const OverStylingInfo = () => {
|
|
22
|
+
const isHighlightActive = useGlobalOverStyled();
|
|
6
23
|
return (
|
|
7
24
|
<Container size="md" style={{ padding: "32px 0" }}>
|
|
8
25
|
<Paper variant="outlined" sx={{ p: 4, borderRadius: 2 }}>
|
|
@@ -172,6 +189,50 @@ export const OverStylingInfo = () => {
|
|
|
172
189
|
|
|
173
190
|
<Divider sx={{ mb: 4 }} />
|
|
174
191
|
|
|
192
|
+
<Title order={6} mb={1}>
|
|
193
|
+
Visual Auditing & Highlights (Development Only)
|
|
194
|
+
</Title>
|
|
195
|
+
<Text mb={2}>
|
|
196
|
+
To make it easy to spot technical debt and design system violations,
|
|
197
|
+
Recursica automatically tracks any component that uses the{" "}
|
|
198
|
+
<code>overStyled={`{true}`}</code> prop.
|
|
199
|
+
</Text>
|
|
200
|
+
<Text mb={2}>
|
|
201
|
+
In <strong>development builds</strong>, you can highlight all
|
|
202
|
+
over-styled components on the page. Open your browser's developer
|
|
203
|
+
console and run:
|
|
204
|
+
</Text>
|
|
205
|
+
<Box
|
|
206
|
+
component="pre"
|
|
207
|
+
sx={{
|
|
208
|
+
p: 1.5,
|
|
209
|
+
bgcolor: "grey.100",
|
|
210
|
+
borderRadius: 1,
|
|
211
|
+
fontSize: 13,
|
|
212
|
+
mt: 1,
|
|
213
|
+
mb: 2,
|
|
214
|
+
}}
|
|
215
|
+
>
|
|
216
|
+
<code>recursica.toggleOverStyled()</code>
|
|
217
|
+
</Box>
|
|
218
|
+
<Stack direction="row" alignItems="center" gap="rec-sm" mb="rec-md">
|
|
219
|
+
<Switch
|
|
220
|
+
label="Highlight Over-Styled Components"
|
|
221
|
+
checked={isHighlightActive}
|
|
222
|
+
onChange={() => toggleGlobalOverStyled()}
|
|
223
|
+
/>
|
|
224
|
+
</Stack>
|
|
225
|
+
<Text mb={4}>
|
|
226
|
+
This toggles a <strong>cyan 2px box shadow</strong> outline around the
|
|
227
|
+
children of all over-styled components. The wrapping elements use{" "}
|
|
228
|
+
<code>display: contents</code> under the hood to ensure they occupy
|
|
229
|
+
zero DOM space and do not affect flex, grid, or absolute positioning
|
|
230
|
+
flow. In production builds, this debugging helper is completely
|
|
231
|
+
disabled and stripped with zero performance overhead.
|
|
232
|
+
</Text>
|
|
233
|
+
|
|
234
|
+
<Divider sx={{ mb: 4 }} />
|
|
235
|
+
|
|
175
236
|
<Title order={6} mb={2}>
|
|
176
237
|
Live Example
|
|
177
238
|
</Title>
|
|
@@ -18,6 +18,7 @@ import { type RecursicaAutocompleteProps as BaseRecursicaAutocompleteProps } fro
|
|
|
18
18
|
|
|
19
19
|
export interface RecursicaAutocompleteProps
|
|
20
20
|
extends Omit<
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
22
|
MuiAutocompleteProps<any, any, any, any, "div">,
|
|
22
23
|
| "variant"
|
|
23
24
|
| "size"
|
|
@@ -32,6 +33,7 @@ export interface RecursicaAutocompleteProps
|
|
|
32
33
|
| "controlMaxWidth"
|
|
33
34
|
| "controlMinWidth"
|
|
34
35
|
| "error"
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
37
|
| keyof MuiAutocompleteProps<any, any, any, any, "div">
|
|
36
38
|
>,
|
|
37
39
|
ReadOnlyControlProps,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Avatar as MuiAvatar,
|
|
4
4
|
type AvatarProps as MuiAvatarProps,
|
|
@@ -74,7 +74,7 @@ const _Avatar = forwardRef<HTMLDivElement, AvatarProps>(function Avatar(
|
|
|
74
74
|
ref={ref}
|
|
75
75
|
className={classNameProp}
|
|
76
76
|
classes={mergedClassNames}
|
|
77
|
-
variant={mapVariant[variant] as
|
|
77
|
+
variant={mapVariant[variant] as unknown as MuiAvatarProps["variant"]}
|
|
78
78
|
src={src}
|
|
79
79
|
data-variant={variant}
|
|
80
80
|
data-size={size}
|
|
@@ -98,4 +98,4 @@ _Avatar.displayName = "Avatar";
|
|
|
98
98
|
*
|
|
99
99
|
* Supports polymorphism via the `component` prop or `renderRoot` for custom element rendering.
|
|
100
100
|
*/
|
|
101
|
-
export const Avatar = _Avatar
|
|
101
|
+
export const Avatar = _Avatar;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Card Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Architecture Overrides
|
|
4
|
+
|
|
5
|
+
Because MUI natively constructs `Card` bounding boxes using `<Paper>` components (which lack the precise edge-to-edge layouts native to Mantine's sections), we implemented custom margins for edge-to-edge section components:
|
|
6
|
+
|
|
7
|
+
- `<Card.Header>` explicitly hooks `--recursica_ui-kit_components_card_properties_header-background` and corresponding padding variables, stretching edge-to-edge via negative margin resets.
|
|
8
|
+
- `<Card.Footer>` explicitly hooks `--recursica_ui-kit_components_card_properties_footer-background` and corresponding padding variables.
|
|
9
|
+
|
|
10
|
+
## Layout Alignment Exceptions
|
|
11
|
+
|
|
12
|
+
To allow Cards to fit cleanly inside dynamic/flex layouts (like dashboard panels, grid tracks, or sidebar layout segments), the Card wrapper implements a custom gatekeeper bypass for outer styling properties:
|
|
13
|
+
|
|
14
|
+
- Exposes a safe subset of flexbox/dimensions styling properties (`flex`, `flexGrow`, `flexShrink`, `flexBasis`, `grow`, `h`, `height`) on the root `<Card>` component to allow proper sizing alongside layout siblings.
|
|
15
|
+
- Sets `<Card.Content>` to `flex-grow: 1;` by default via CSS modules. Since the root `<Card>` has `display: flex; flex-direction: column;`, this makes the content area expand to fill all vertical space, pushing `<Card.Footer>` to align at the absolute bottom of the bounding box.
|
|
@@ -12,7 +12,17 @@ import {
|
|
|
12
12
|
} from "@recursica/adapter-common";
|
|
13
13
|
|
|
14
14
|
// ==== CARD CONTAINER ====
|
|
15
|
-
export type CardProps = RecursicaOverStyled<
|
|
15
|
+
export type CardProps = RecursicaOverStyled<
|
|
16
|
+
MuiCardProps & RecursicaCardProps
|
|
17
|
+
> & {
|
|
18
|
+
flex?: string | number;
|
|
19
|
+
flexGrow?: string | number;
|
|
20
|
+
flexShrink?: string | number;
|
|
21
|
+
flexBasis?: string | number;
|
|
22
|
+
grow?: string | number;
|
|
23
|
+
h?: string | number;
|
|
24
|
+
height?: string | number;
|
|
25
|
+
};
|
|
16
26
|
|
|
17
27
|
/**
|
|
18
28
|
* The root Card elevation box. It establishes the global background color, border radius, nested component gap, and outer shadow governed by the current `Layer` context.
|
|
@@ -23,6 +33,24 @@ const CardBase = forwardRef<HTMLDivElement, CardProps>(function Card(
|
|
|
23
33
|
) {
|
|
24
34
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
25
35
|
|
|
36
|
+
// Expose outer layout/flexbox properties on Card to allow structuring alongside siblings
|
|
37
|
+
const safeCardLayoutKeys = [
|
|
38
|
+
"flex",
|
|
39
|
+
"flexGrow",
|
|
40
|
+
"flexShrink",
|
|
41
|
+
"flexBasis",
|
|
42
|
+
"grow",
|
|
43
|
+
"h",
|
|
44
|
+
"height",
|
|
45
|
+
] as const;
|
|
46
|
+
safeCardLayoutKeys.forEach((key) => {
|
|
47
|
+
if (key in rest && !(key in sanitizedProps)) {
|
|
48
|
+
(sanitizedProps as Record<string, unknown>)[key] = (
|
|
49
|
+
rest as Record<string, unknown>
|
|
50
|
+
)[key];
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
26
54
|
const mergedClassNames: Partial<Record<string, string>> = {
|
|
27
55
|
root: styles.root,
|
|
28
56
|
};
|
|
@@ -167,7 +195,7 @@ CardContent.displayName = "CardContent";
|
|
|
167
195
|
* Supports polymorphism via the `component` prop or `renderRoot` for custom element rendering.
|
|
168
196
|
* Use dot-notation sub-components for structured card layouts.
|
|
169
197
|
*/
|
|
170
|
-
const PolymorphicCard = CardBase
|
|
198
|
+
const PolymorphicCard = CardBase;
|
|
171
199
|
|
|
172
200
|
// Attach static components for dot-notation access
|
|
173
201
|
const _card = PolymorphicCard as unknown as Record<string, unknown>;
|
|
@@ -133,7 +133,12 @@ export const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(
|
|
|
133
133
|
}
|
|
134
134
|
} else {
|
|
135
135
|
if (restRecord.onChange) {
|
|
136
|
-
(
|
|
136
|
+
(
|
|
137
|
+
restRecord.onChange as (
|
|
138
|
+
event: React.ChangeEvent<HTMLInputElement>,
|
|
139
|
+
checked: boolean,
|
|
140
|
+
) => void
|
|
141
|
+
)(e, e.target.checked);
|
|
137
142
|
}
|
|
138
143
|
}
|
|
139
144
|
};
|
|
@@ -21,7 +21,10 @@ export const CheckboxGroupContext = React.createContext<{
|
|
|
21
21
|
import { type RecursicaCheckboxGroupProps as BaseRecursicaCheckboxGroupProps } from "@recursica/adapter-common";
|
|
22
22
|
|
|
23
23
|
export interface RecursicaCheckboxGroupProps
|
|
24
|
-
extends Omit<
|
|
24
|
+
extends Omit<
|
|
25
|
+
React.HTMLAttributes<HTMLDivElement>,
|
|
26
|
+
"onChange" | "defaultValue"
|
|
27
|
+
>,
|
|
25
28
|
Omit<
|
|
26
29
|
RecursicaFormControlWrapperProps,
|
|
27
30
|
| "controlMaxWidth"
|
|
@@ -29,6 +32,7 @@ export interface RecursicaCheckboxGroupProps
|
|
|
29
32
|
| "onChange"
|
|
30
33
|
| "classes"
|
|
31
34
|
| "withAsterisk"
|
|
35
|
+
| "defaultValue"
|
|
32
36
|
>,
|
|
33
37
|
ReadOnlyControlProps,
|
|
34
38
|
BaseRecursicaCheckboxGroupProps {}
|
|
@@ -112,7 +116,7 @@ export const CheckboxGroup = forwardRef<HTMLDivElement, CheckboxGroupProps>(
|
|
|
112
116
|
activeComponent={
|
|
113
117
|
<CheckboxGroupContext.Provider
|
|
114
118
|
value={{
|
|
115
|
-
value: value !== undefined ? value : defaultValue,
|
|
119
|
+
value: (value !== undefined ? value : defaultValue) as any[],
|
|
116
120
|
onChange: handleChange,
|
|
117
121
|
name: restRecord.name as string | undefined,
|
|
118
122
|
readOnly: readOnly || !!(restRecord as any).disabled,
|
|
@@ -6,16 +6,18 @@
|
|
|
6
6
|
* (Stack, Group, Flex), Container explicitly ALLOWS the `sx` prop as an escape hatch
|
|
7
7
|
* for advanced layout positioning.
|
|
8
8
|
*/
|
|
9
|
-
import
|
|
9
|
+
import { forwardRef } from "react";
|
|
10
10
|
import {
|
|
11
11
|
Container as MUIContainer,
|
|
12
12
|
type ContainerProps as MUIContainerProps,
|
|
13
13
|
} from "@mui/material";
|
|
14
14
|
|
|
15
|
+
import { type WithRecursicaSpacing } from "../../utils/filterStylingProps";
|
|
15
16
|
import { type RecursicaContainerProps } from "@recursica/adapter-common";
|
|
16
17
|
|
|
17
|
-
export type ContainerProps =
|
|
18
|
-
RecursicaContainerProps
|
|
18
|
+
export type ContainerProps = WithRecursicaSpacing<
|
|
19
|
+
Omit<MUIContainerProps, "maxWidth"> & RecursicaContainerProps
|
|
20
|
+
>;
|
|
19
21
|
|
|
20
22
|
export const Container = forwardRef<HTMLDivElement, ContainerProps>(
|
|
21
23
|
function Container({ children, size, ...rest }, ref) {
|
|
@@ -18,18 +18,17 @@ import { type RecursicaDropdownProps as BaseRecursicaDropdownProps } from "@recu
|
|
|
18
18
|
export interface RecursicaDropdownProps
|
|
19
19
|
extends Omit<
|
|
20
20
|
MuiSelectProps,
|
|
21
|
-
|
|
21
|
+
| keyof React.HTMLAttributes<HTMLDivElement>
|
|
22
|
+
| "size"
|
|
23
|
+
| "variant"
|
|
24
|
+
| "classes"
|
|
25
|
+
| "inputProps"
|
|
26
|
+
| "SelectDisplayProps"
|
|
27
|
+
| "ref"
|
|
22
28
|
>,
|
|
23
|
-
|
|
29
|
+
Omit<
|
|
24
30
|
RecursicaFormControlWrapperProps,
|
|
25
|
-
| "
|
|
26
|
-
| "assistiveWithIcon"
|
|
27
|
-
| "formLayout"
|
|
28
|
-
| "labelSize"
|
|
29
|
-
| "labelAlignment"
|
|
30
|
-
| "labelOptionalText"
|
|
31
|
-
| "labelWithEditIcon"
|
|
32
|
-
| "onLabelEditClick"
|
|
31
|
+
"controlMaxWidth" | "controlMinWidth"
|
|
33
32
|
>,
|
|
34
33
|
ReadOnlyControlProps,
|
|
35
34
|
BaseRecursicaDropdownProps {}
|
|
@@ -167,7 +166,7 @@ export const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
|
|
|
167
166
|
inputProps={{
|
|
168
167
|
"data-disabled": disabled ? "true" : undefined,
|
|
169
168
|
"data-error": error ? "true" : undefined,
|
|
170
|
-
...(restRecord.inputProps as
|
|
169
|
+
...(restRecord.inputProps as Record<string, unknown>),
|
|
171
170
|
}}
|
|
172
171
|
{...(sanitizedProps as unknown as MuiSelectProps)}
|
|
173
172
|
>
|
|
@@ -8,17 +8,20 @@
|
|
|
8
8
|
* Like Stack and Group, this is a primitive layout component. It strictly filters out the
|
|
9
9
|
* `sx` prop using `OmitSx` and `filterSxProp` to enforce the use of standard layout scales.
|
|
10
10
|
*/
|
|
11
|
-
import
|
|
11
|
+
import { forwardRef } from "react";
|
|
12
12
|
import { Box as MUIBox, type BoxProps as MUIBoxProps } from "@mui/material";
|
|
13
13
|
import {
|
|
14
14
|
SPACING_MAP,
|
|
15
15
|
type OmitSx,
|
|
16
16
|
filterSxProp,
|
|
17
|
+
type WithRecursicaSpacing,
|
|
17
18
|
} from "../../utils/filterStylingProps";
|
|
18
19
|
|
|
19
20
|
import { type RecursicaFlexProps } from "@recursica/adapter-common";
|
|
20
21
|
|
|
21
|
-
export type FlexProps =
|
|
22
|
+
export type FlexProps = WithRecursicaSpacing<
|
|
23
|
+
OmitSx<MUIBoxProps & RecursicaFlexProps>
|
|
24
|
+
>;
|
|
22
25
|
|
|
23
26
|
export const Flex = forwardRef<HTMLDivElement, FlexProps>(function Flex(
|
|
24
27
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Stack as MUIStack,
|
|
4
4
|
type StackProps as MUIStackProps,
|
|
@@ -7,12 +7,13 @@ import {
|
|
|
7
7
|
SPACING_MAP,
|
|
8
8
|
type OmitSx,
|
|
9
9
|
filterSxProp,
|
|
10
|
+
type WithRecursicaSpacing,
|
|
10
11
|
} from "../../utils/filterStylingProps";
|
|
11
12
|
|
|
12
13
|
import { type RecursicaGroupProps } from "@recursica/adapter-common";
|
|
13
14
|
|
|
14
|
-
export type GroupProps =
|
|
15
|
-
Omit<MUIStackProps, "spacing" | "direction"> & RecursicaGroupProps
|
|
15
|
+
export type GroupProps = WithRecursicaSpacing<
|
|
16
|
+
OmitSx<Omit<MUIStackProps, "spacing" | "direction"> & RecursicaGroupProps>
|
|
16
17
|
>;
|
|
17
18
|
|
|
18
19
|
export const Group = forwardRef<HTMLDivElement, GroupProps>(function Group(
|
|
@@ -63,7 +63,10 @@ const HoverCardBase = function HoverCard({
|
|
|
63
63
|
|
|
64
64
|
React.Children.forEach(children, (child) => {
|
|
65
65
|
if (isValidElement(child)) {
|
|
66
|
-
const childElement = child as
|
|
66
|
+
const childElement = child as unknown as {
|
|
67
|
+
type?: { displayName?: string };
|
|
68
|
+
props: { children?: React.ReactNode };
|
|
69
|
+
};
|
|
67
70
|
if (childElement.type?.displayName === "HoverCardTarget") {
|
|
68
71
|
targetNode = childElement.props.children;
|
|
69
72
|
} else if (childElement.type?.displayName === "HoverCardDropdown") {
|
|
@@ -83,7 +86,7 @@ const HoverCardBase = function HoverCard({
|
|
|
83
86
|
return (
|
|
84
87
|
<MuiTooltip
|
|
85
88
|
title={dropdownNode}
|
|
86
|
-
placement={position as
|
|
89
|
+
placement={position as unknown as MuiTooltipProps["placement"]}
|
|
87
90
|
arrow={withBeak}
|
|
88
91
|
enterDelay={openDelay}
|
|
89
92
|
leaveDelay={closeDelay}
|
|
@@ -100,8 +103,8 @@ const HoverCardBase = function HoverCard({
|
|
|
100
103
|
],
|
|
101
104
|
},
|
|
102
105
|
}}
|
|
103
|
-
classes={mergedClassNames as
|
|
104
|
-
{...(sanitizedProps as
|
|
106
|
+
classes={mergedClassNames as unknown as MuiTooltipProps["classes"]}
|
|
107
|
+
{...(sanitizedProps as unknown as Record<string, unknown>)}
|
|
105
108
|
>
|
|
106
109
|
{/* Tooltip requires a single valid React element child that accepts a ref */}
|
|
107
110
|
{isValidElement(targetNode) ? targetNode : <span>{targetNode}</span>}
|
|
@@ -13,7 +13,7 @@ import { Menu, MenuItem, MenuDivider } from "./Menu";
|
|
|
13
13
|
import { Button } from "../Button";
|
|
14
14
|
import { ListSubheader } from "@mui/material";
|
|
15
15
|
|
|
16
|
-
const SettingsIcon = (props:
|
|
16
|
+
const SettingsIcon = (props: React.ComponentProps<"svg">) => (
|
|
17
17
|
<svg
|
|
18
18
|
xmlns="http://www.w3.org/2000/svg"
|
|
19
19
|
width="14"
|
|
@@ -31,7 +31,7 @@ const SettingsIcon = (props: any) => (
|
|
|
31
31
|
</svg>
|
|
32
32
|
);
|
|
33
33
|
|
|
34
|
-
const SearchIcon = (props:
|
|
34
|
+
const SearchIcon = (props: React.ComponentProps<"svg">) => (
|
|
35
35
|
<svg
|
|
36
36
|
xmlns="http://www.w3.org/2000/svg"
|
|
37
37
|
width="14"
|
|
@@ -49,7 +49,7 @@ const SearchIcon = (props: any) => (
|
|
|
49
49
|
</svg>
|
|
50
50
|
);
|
|
51
51
|
|
|
52
|
-
const MessageIcon = (props:
|
|
52
|
+
const MessageIcon = (props: React.ComponentProps<"svg">) => (
|
|
53
53
|
<svg
|
|
54
54
|
xmlns="http://www.w3.org/2000/svg"
|
|
55
55
|
width="14"
|
|
@@ -66,7 +66,7 @@ const MessageIcon = (props: any) => (
|
|
|
66
66
|
</svg>
|
|
67
67
|
);
|
|
68
68
|
|
|
69
|
-
const ImageIcon = (props:
|
|
69
|
+
const ImageIcon = (props: React.ComponentProps<"svg">) => (
|
|
70
70
|
<svg
|
|
71
71
|
xmlns="http://www.w3.org/2000/svg"
|
|
72
72
|
width="14"
|
|
@@ -85,7 +85,7 @@ const ImageIcon = (props: any) => (
|
|
|
85
85
|
</svg>
|
|
86
86
|
);
|
|
87
87
|
|
|
88
|
-
const TrashIcon = (props:
|
|
88
|
+
const TrashIcon = (props: React.ComponentProps<"svg">) => (
|
|
89
89
|
<svg
|
|
90
90
|
xmlns="http://www.w3.org/2000/svg"
|
|
91
91
|
width="14"
|
|
@@ -103,7 +103,7 @@ const TrashIcon = (props: any) => (
|
|
|
103
103
|
</svg>
|
|
104
104
|
);
|
|
105
105
|
|
|
106
|
-
const ArrowsIcon = (props:
|
|
106
|
+
const ArrowsIcon = (props: React.ComponentProps<"svg">) => (
|
|
107
107
|
<svg
|
|
108
108
|
xmlns="http://www.w3.org/2000/svg"
|
|
109
109
|
width="14"
|
|
@@ -123,7 +123,7 @@ const ArrowsIcon = (props: any) => (
|
|
|
123
123
|
</svg>
|
|
124
124
|
);
|
|
125
125
|
|
|
126
|
-
type MenuStoryArgs = Record<string,
|
|
126
|
+
type MenuStoryArgs = Record<string, unknown>;
|
|
127
127
|
|
|
128
128
|
const meta: Meta = {
|
|
129
129
|
title: "UI-Kit/Menu",
|
|
@@ -135,7 +135,13 @@ export default meta;
|
|
|
135
135
|
|
|
136
136
|
type Story = StoryObj<MenuStoryArgs>;
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
interface InteractiveMenuProps {
|
|
139
|
+
children?: React.ReactNode;
|
|
140
|
+
opened?: boolean;
|
|
141
|
+
[key: string]: unknown;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const InteractiveMenu = ({ children, ...args }: InteractiveMenuProps) => {
|
|
139
145
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
|
140
146
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
141
147
|
|