@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
|
@@ -65,7 +65,8 @@ const ModalRoot = forwardRef<HTMLDivElement, ModalProps>(function ModalRoot(
|
|
|
65
65
|
if (
|
|
66
66
|
React.isValidElement(child) &&
|
|
67
67
|
(child.type === ModalFooter ||
|
|
68
|
-
(child.type as
|
|
68
|
+
(child.type as unknown as { displayName?: string })?.displayName ===
|
|
69
|
+
"Modal.Footer")
|
|
69
70
|
) {
|
|
70
71
|
footer = child;
|
|
71
72
|
} else {
|
|
@@ -81,7 +82,11 @@ const ModalRoot = forwardRef<HTMLDivElement, ModalProps>(function ModalRoot(
|
|
|
81
82
|
paper: styles.inner,
|
|
82
83
|
}}
|
|
83
84
|
{...(sanitizedProps as MuiDialogProps)}
|
|
84
|
-
open={
|
|
85
|
+
open={
|
|
86
|
+
opened ||
|
|
87
|
+
((sanitizedProps as Record<string, unknown>).open as boolean) ||
|
|
88
|
+
false
|
|
89
|
+
}
|
|
85
90
|
onClose={onClose}
|
|
86
91
|
>
|
|
87
92
|
{(title || withCloseButton) && (
|
|
@@ -117,6 +122,7 @@ const ModalTitle = forwardRef<HTMLDivElement, ModalTitleProps>(
|
|
|
117
122
|
|
|
118
123
|
return (
|
|
119
124
|
<MuiDialogTitle
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
120
126
|
ref={ref as any}
|
|
121
127
|
className={`${styles.title} ${className || ""}`}
|
|
122
128
|
{...(sanitizedProps as MuiDialogTitleProps)}
|
|
@@ -159,10 +165,10 @@ const ModalBody = forwardRef<HTMLDivElement, ModalBodyProps>(function ModalBody(
|
|
|
159
165
|
return (
|
|
160
166
|
<MuiDialogContent
|
|
161
167
|
ref={(node) => {
|
|
162
|
-
if (typeof ref === "function") ref(node as
|
|
168
|
+
if (typeof ref === "function") ref(node as HTMLDivElement);
|
|
163
169
|
else if (ref)
|
|
164
170
|
(ref as React.MutableRefObject<HTMLDivElement | null>).current =
|
|
165
|
-
node as
|
|
171
|
+
node as HTMLDivElement;
|
|
166
172
|
if (internalRef)
|
|
167
173
|
(
|
|
168
174
|
internalRef as React.MutableRefObject<HTMLDivElement | null>
|
|
@@ -193,6 +199,7 @@ const ModalFooter = forwardRef<HTMLDivElement, ModalFooterProps>(
|
|
|
193
199
|
|
|
194
200
|
return (
|
|
195
201
|
<MuiDialogActions
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
196
203
|
ref={ref as any}
|
|
197
204
|
className={`${styles.footer} ${className || ""}`}
|
|
198
205
|
{...(sanitizedProps as MuiDialogActionsProps)}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Panel – Implementation Notes
|
|
2
|
+
|
|
3
|
+
Decisions and design tweaks strictly tailored for the UI Kit's Panel wrapped against `@mui/material`. This is a living document that tracks _why_ specific logic decisions exist.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Mapping to MUI Drawer
|
|
8
|
+
|
|
9
|
+
**Decision:** Panel maps to MUI's `Drawer` component, not `Paper` or `Card`.
|
|
10
|
+
|
|
11
|
+
**Implementation:** Per the Recursica design system specification, "Panels slide in or expand from the edge of the screen to reveal additional content or functionality." This is the exact behavior of MUI's `Drawer` component, which provides:
|
|
12
|
+
|
|
13
|
+
- Slide-in animation from any screen edge (using the `anchor` prop)
|
|
14
|
+
- Backdrop/overlay support
|
|
15
|
+
- Focus trap and overlay portal management
|
|
16
|
+
- Internal scroll lock when open
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 2. Token Namespace: `panel`
|
|
21
|
+
|
|
22
|
+
**Decision:** The CSS module exclusively uses variables from the `--recursica_ui-kit_components_panel_*` namespace.
|
|
23
|
+
|
|
24
|
+
**Implementation:** The Recursica token system defines the `panel` namespace covering:
|
|
25
|
+
|
|
26
|
+
- Geometry: border-radius, border-size, min-width (200px), max-width (960px)
|
|
27
|
+
- Content padding: content-horizontal-padding (xl), content-vertical-padding (lg)
|
|
28
|
+
- Header/Footer padding: header-footer-horizontal-padding (xl), header-footer-vertical-padding (md)
|
|
29
|
+
- Spacing: header-close-gap (md), footer-button-gap (md)
|
|
30
|
+
- Divider: divider-size (1px), divider-color
|
|
31
|
+
- Elevation: elevation-3
|
|
32
|
+
- Colors (layer-aware): background, border-color, content, divider-color, header-footer-background, title
|
|
33
|
+
- Non-CSS: header-style ("h3")
|
|
34
|
+
|
|
35
|
+
No tokens from other component namespaces are referenced.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 3. Default Placement Override
|
|
40
|
+
|
|
41
|
+
**Decision:** Use `placement` instead of `position` for configuring slide-out direction, and default it to `"right"`.
|
|
42
|
+
|
|
43
|
+
**Implementation:** The prop was renamed from `position` to `placement` to prevent collision with the CSS `position` keyword, which is strictly blocked by the styling gatekeeper (`BLOCKED_STYLING_KEYS`). This allows configuring the drawer direction natively while maintaining strict design-system boundaries. The `placement="right"` default is mapped internally to MUI Drawer's `anchor` prop before any other sanitized props are applied. Right-side panels are the most common pattern for supplementary content, settings, and detail views.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 4. Custom Panel.Footer
|
|
48
|
+
|
|
49
|
+
**Decision:** A custom `Panel.Footer` sub-component is provided. MUI's Drawer does not have a native footer.
|
|
50
|
+
|
|
51
|
+
**Implementation:** `Panel.Footer` is a `<div>` with styling referencing Recursica CSS variables for:
|
|
52
|
+
|
|
53
|
+
- `header-footer-background` and `header-footer-padding` tokens
|
|
54
|
+
- Top divider using `divider-size` and `divider-color`
|
|
55
|
+
- `footer-button-gap` for action button spacing
|
|
56
|
+
- `margin-top: auto` to push the footer to the bottom
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 5. Visibility Mapping (`opened` -> `open`)
|
|
61
|
+
|
|
62
|
+
**Decision:** Accept `opened` prop to match the standard Recursica component API.
|
|
63
|
+
|
|
64
|
+
**Implementation:** MUI Drawer natively expects the `open` boolean prop. The wrapper maps the incoming framework-agnostic `opened` prop to MUI's `open={Boolean(opened)}`, allowing consistent usage across both adapter implementations.
|
|
@@ -12,7 +12,7 @@ const meta: Meta = {
|
|
|
12
12
|
component: Panel,
|
|
13
13
|
tags: ["autodocs"],
|
|
14
14
|
argTypes: {
|
|
15
|
-
|
|
15
|
+
placement: {
|
|
16
16
|
control: "select",
|
|
17
17
|
options: ["left", "right", "top", "bottom"],
|
|
18
18
|
description: "Side of the screen the panel slides in from.",
|
|
@@ -45,7 +45,7 @@ const meta: Meta = {
|
|
|
45
45
|
docs: {
|
|
46
46
|
description: {
|
|
47
47
|
component: `
|
|
48
|
-
The \`Panel\` component slides in or expands from the edge of the screen to reveal additional content or functionality. Built on
|
|
48
|
+
The \`Panel\` component slides in or expands from the edge of the screen to reveal additional content or functionality. Built on Mui's \`Drawer\`, it enforces Recursica design tokens for styling.
|
|
49
49
|
|
|
50
50
|
### Anatomy
|
|
51
51
|
1. **Header** — Title and close icon, remains fixed on scroll
|
|
@@ -58,7 +58,7 @@ The \`Panel\` component slides in or expands from the edge of the screen to reve
|
|
|
58
58
|
const [opened, { open, close }] = useDisclosure(false);
|
|
59
59
|
|
|
60
60
|
<Button onClick={open}>Open Panel</Button>
|
|
61
|
-
<Panel opened={opened} onClose={close} title="Settings"
|
|
61
|
+
<Panel opened={opened} onClose={close} title="Settings" placement="right">
|
|
62
62
|
Content goes here
|
|
63
63
|
<Panel.Footer>
|
|
64
64
|
<Button variant="outline">Cancel</Button>
|
|
@@ -78,7 +78,7 @@ type Story = StoryObj<PanelStoryArgs>;
|
|
|
78
78
|
|
|
79
79
|
export const Default: Story = {
|
|
80
80
|
args: {
|
|
81
|
-
|
|
81
|
+
placement: "right",
|
|
82
82
|
title: "Panel Title",
|
|
83
83
|
withOverlay: true,
|
|
84
84
|
withCloseButton: true,
|
|
@@ -98,7 +98,7 @@ export const Default: Story = {
|
|
|
98
98
|
opened={opened}
|
|
99
99
|
onClose={() => setOpened(false)}
|
|
100
100
|
title="Panel Title"
|
|
101
|
-
|
|
101
|
+
placement="right"
|
|
102
102
|
wrapHeaderText={wrapHeaderText}
|
|
103
103
|
>
|
|
104
104
|
<Text>
|
|
@@ -118,9 +118,9 @@ export const Default: Story = {
|
|
|
118
118
|
},
|
|
119
119
|
};
|
|
120
120
|
|
|
121
|
-
export const
|
|
121
|
+
export const LeftPlacement: Story = {
|
|
122
122
|
args: {
|
|
123
|
-
|
|
123
|
+
placement: "left",
|
|
124
124
|
title: "Navigation",
|
|
125
125
|
withOverlay: true,
|
|
126
126
|
withCloseButton: true,
|
|
@@ -153,7 +153,7 @@ export const LeftPosition: Story = {
|
|
|
153
153
|
|
|
154
154
|
export const ScrollableContent: Story = {
|
|
155
155
|
args: {
|
|
156
|
-
|
|
156
|
+
placement: "right",
|
|
157
157
|
title: "Scrollable Panel",
|
|
158
158
|
withOverlay: true,
|
|
159
159
|
withCloseButton: true,
|
|
@@ -195,7 +195,7 @@ export const ScrollableContent: Story = {
|
|
|
195
195
|
|
|
196
196
|
export const LongTitle: Story = {
|
|
197
197
|
args: {
|
|
198
|
-
|
|
198
|
+
placement: "right",
|
|
199
199
|
title:
|
|
200
200
|
"This is a ridiculously long panel title designed to test how the header CSS handles text overflow and whether it truncates correctly or breaks the layout",
|
|
201
201
|
withOverlay: true,
|
|
@@ -13,11 +13,18 @@ import styles from "./Panel.module.css";
|
|
|
13
13
|
// PANEL (Drawer)
|
|
14
14
|
// ============================================================
|
|
15
15
|
|
|
16
|
-
import { type RecursicaPanelProps } from "@recursica/adapter-common";
|
|
16
|
+
import { type RecursicaPanelProps as BaseRecursicaPanelProps } from "@recursica/adapter-common";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Recursica Panel root props. Extends Mui Drawer.
|
|
20
20
|
*/
|
|
21
|
+
export interface RecursicaPanelProps
|
|
22
|
+
extends Omit<
|
|
23
|
+
MuiDrawerProps,
|
|
24
|
+
"classes" | "position" | "style" | "anchor" | "open"
|
|
25
|
+
>,
|
|
26
|
+
BaseRecursicaPanelProps {}
|
|
27
|
+
|
|
21
28
|
export type PanelProps = RecursicaOverStyled<RecursicaPanelProps>;
|
|
22
29
|
|
|
23
30
|
/**
|
|
@@ -29,7 +36,7 @@ export type PanelProps = RecursicaOverStyled<RecursicaPanelProps>;
|
|
|
29
36
|
* cluttering the main interface.
|
|
30
37
|
*
|
|
31
38
|
* ```tsx
|
|
32
|
-
* <Panel opened={opened} onClose={close} title="Panel Title"
|
|
39
|
+
* <Panel opened={opened} onClose={close} title="Panel Title" placement="right">
|
|
33
40
|
* <Panel.Body>
|
|
34
41
|
* Content goes here
|
|
35
42
|
* </Panel.Body>
|
|
@@ -48,14 +55,12 @@ export type PanelProps = RecursicaOverStyled<RecursicaPanelProps>;
|
|
|
48
55
|
*/
|
|
49
56
|
const PanelBase = function Panel({
|
|
50
57
|
overStyled = false,
|
|
51
|
-
|
|
58
|
+
placement = "right",
|
|
52
59
|
keepMounted = true,
|
|
53
60
|
wrapHeaderText = false,
|
|
61
|
+
opened,
|
|
54
62
|
...rest
|
|
55
|
-
}: PanelProps
|
|
56
|
-
position?: "left" | "right" | "top" | "bottom";
|
|
57
|
-
opened?: boolean;
|
|
58
|
-
}) {
|
|
63
|
+
}: PanelProps) {
|
|
59
64
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
60
65
|
|
|
61
66
|
// Bind CSS module classes to Mui's internal classNames API
|
|
@@ -85,9 +90,9 @@ const PanelBase = function Panel({
|
|
|
85
90
|
|
|
86
91
|
return (
|
|
87
92
|
<MuiDrawer
|
|
88
|
-
anchor={
|
|
93
|
+
anchor={placement} /* Recursica default: right; Mui default: left */
|
|
89
94
|
keepMounted={keepMounted}
|
|
90
|
-
open={Boolean(
|
|
95
|
+
open={Boolean(opened)}
|
|
91
96
|
{...(sanitizedProps as unknown as MuiDrawerProps)}
|
|
92
97
|
classes={mergedClassNames}
|
|
93
98
|
/>
|
|
@@ -147,6 +147,7 @@ export const Radio = forwardRef<HTMLInputElement, RadioProps>(
|
|
|
147
147
|
// We omit Mui's sizing/coloring so we rely strictly on variables from Radio.module.css
|
|
148
148
|
const radioNode = (
|
|
149
149
|
<MuiRadio
|
|
150
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
150
151
|
ref={ref as any}
|
|
151
152
|
icon={<RadioIcon />}
|
|
152
153
|
checkedIcon={<RadioIcon className={styles.checked} />}
|
|
@@ -81,7 +81,7 @@ export const ReadOnlyField = React.forwardRef<
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// Type coercions securely bounding the output values cleanly explicitly.
|
|
84
|
-
let displayValue: React.ReactNode = value;
|
|
84
|
+
let displayValue: React.ReactNode = value as any;
|
|
85
85
|
|
|
86
86
|
if (type === "boolean" || type === "switch") {
|
|
87
87
|
displayValue = value ? "True" : "False";
|
|
@@ -108,7 +108,11 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
|
108
108
|
data-orientation={orientation}
|
|
109
109
|
exclusive
|
|
110
110
|
value={value}
|
|
111
|
-
onChange={
|
|
111
|
+
onChange={
|
|
112
|
+
handleChange as React.ComponentProps<
|
|
113
|
+
typeof MuiSegmentedControl
|
|
114
|
+
>["onChange"]
|
|
115
|
+
}
|
|
112
116
|
{...(sanitizedProps as Omit<
|
|
113
117
|
MuiSegmentedControlProps,
|
|
114
118
|
"variant" | "size" | "value" | "onChange"
|
|
@@ -129,7 +129,7 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
129
129
|
if (!isNaN(parsed)) {
|
|
130
130
|
// Clamp input value to bounds
|
|
131
131
|
const clamped = Math.max(min, Math.min(max, parsed));
|
|
132
|
-
handleValueChange(null as
|
|
132
|
+
handleValueChange(null as unknown as Event, clamped);
|
|
133
133
|
}
|
|
134
134
|
};
|
|
135
135
|
|
|
@@ -211,7 +211,7 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
211
211
|
label={label}
|
|
212
212
|
assistiveText={assistiveText}
|
|
213
213
|
assistiveWithIcon={assistiveWithIcon}
|
|
214
|
-
error={error
|
|
214
|
+
error={!!error}
|
|
215
215
|
required={required}
|
|
216
216
|
id={id}
|
|
217
217
|
readOnly={readOnly}
|
|
@@ -239,14 +239,22 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
239
239
|
disabled={disabled}
|
|
240
240
|
value={resolvedValue}
|
|
241
241
|
onChange={handleValueChange}
|
|
242
|
-
onChangeCommitted={
|
|
242
|
+
onChangeCommitted={
|
|
243
|
+
onChangeEnd as unknown as (
|
|
244
|
+
event: Event | React.SyntheticEvent,
|
|
245
|
+
value: number | number[],
|
|
246
|
+
) => void
|
|
247
|
+
}
|
|
243
248
|
min={min}
|
|
244
249
|
max={max}
|
|
245
250
|
step={step}
|
|
246
251
|
valueLabelDisplay={tooltipLabel === null ? "off" : "auto"}
|
|
247
252
|
valueLabelFormat={
|
|
248
253
|
typeof tooltipLabel === "function"
|
|
249
|
-
? (tooltipLabel as
|
|
254
|
+
? (tooltipLabel as unknown as (
|
|
255
|
+
value: number,
|
|
256
|
+
index: number,
|
|
257
|
+
) => React.ReactNode)
|
|
250
258
|
: undefined
|
|
251
259
|
}
|
|
252
260
|
{...(sanitizedProps as unknown as MuiSliderProps)}
|
|
@@ -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 RecursicaStackProps } from "@recursica/adapter-common";
|
|
13
14
|
|
|
14
|
-
export type StackProps =
|
|
15
|
-
Omit<MUIStackProps, "spacing"> & RecursicaStackProps
|
|
15
|
+
export type StackProps = WithRecursicaSpacing<
|
|
16
|
+
OmitSx<Omit<MUIStackProps, "spacing"> & RecursicaStackProps>
|
|
16
17
|
>;
|
|
17
18
|
|
|
18
19
|
export const Stack = forwardRef<HTMLDivElement, StackProps>(function Stack(
|
|
@@ -19,7 +19,11 @@ import styles from "./Stepper.module.css";
|
|
|
19
19
|
|
|
20
20
|
import { type RecursicaStepperProps } from "@recursica/adapter-common";
|
|
21
21
|
|
|
22
|
-
export
|
|
22
|
+
export interface RecursicaStepperPropsExtended
|
|
23
|
+
extends Omit<Partial<MuiStepperProps>, "size">,
|
|
24
|
+
RecursicaStepperProps {}
|
|
25
|
+
|
|
26
|
+
export type StepperProps = RecursicaOverStyled<RecursicaStepperPropsExtended>;
|
|
23
27
|
|
|
24
28
|
export const Stepper = forwardRef<HTMLDivElement, StepperProps>(
|
|
25
29
|
function Stepper(props, ref) {
|
|
@@ -42,6 +46,7 @@ export const Stepper = forwardRef<HTMLDivElement, StepperProps>(
|
|
|
42
46
|
data-orientation={orientation}
|
|
43
47
|
>
|
|
44
48
|
<MuiStepper
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
50
|
ref={ref as any}
|
|
46
51
|
orientation={orientation}
|
|
47
52
|
connector={
|
|
@@ -37,7 +37,7 @@ export type RecursicaSwitchPropsAlias =
|
|
|
37
37
|
|
|
38
38
|
export type SwitchProps = RecursicaOverStyled<RecursicaSwitchPropsAlias>;
|
|
39
39
|
|
|
40
|
-
type SwitchComponent =
|
|
40
|
+
type SwitchComponent = React.ComponentType<SwitchProps>;
|
|
41
41
|
|
|
42
42
|
export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
|
|
43
43
|
function Switch(props, ref) {
|
|
@@ -137,6 +137,7 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
|
|
|
137
137
|
// We omit Mui's sizing/coloring so we rely strictly on variables from Switch.module.css
|
|
138
138
|
const switchNode = (
|
|
139
139
|
<MuiSwitch
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
141
|
ref={ref as any}
|
|
141
142
|
className={!label ? `${finalClass} ${styles.inner}` : styles.inner}
|
|
142
143
|
classes={mergedClassNames}
|
|
@@ -28,7 +28,11 @@ export interface RecursicaSwitchGroupProps
|
|
|
28
28
|
>,
|
|
29
29
|
Omit<
|
|
30
30
|
RecursicaFormControlWrapperProps,
|
|
31
|
-
|
|
31
|
+
| "controlMaxWidth"
|
|
32
|
+
| "controlMinWidth"
|
|
33
|
+
| "classes"
|
|
34
|
+
| "onChange"
|
|
35
|
+
| "defaultValue"
|
|
32
36
|
>,
|
|
33
37
|
ReadOnlyControlProps,
|
|
34
38
|
BaseRecursicaSwitchGroupProps {}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { Table } from "./Table";
|
|
3
|
-
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
3
|
|
|
5
4
|
const meta: Meta<typeof Table> = {
|
|
6
|
-
title: "UI-Kit
|
|
5
|
+
title: "UI-Kit/Table",
|
|
7
6
|
component: Table,
|
|
8
7
|
tags: ["autodocs"],
|
|
9
8
|
};
|
|
@@ -12,6 +11,39 @@ export default meta;
|
|
|
12
11
|
|
|
13
12
|
type Story = StoryObj<typeof Table>;
|
|
14
13
|
|
|
14
|
+
const elements = [
|
|
15
|
+
{ position: 6, mass: 12.011, symbol: "C", name: "Carbon" },
|
|
16
|
+
{ position: 7, mass: 14.007, symbol: "N", name: "Nitrogen" },
|
|
17
|
+
{ position: 8, mass: 15.999, symbol: "O", name: "Oxygen" },
|
|
18
|
+
{ position: 9, mass: 18.998, symbol: "F", name: "Fluorine" },
|
|
19
|
+
{ position: 10, mass: 20.18, symbol: "Ne", name: "Neon" },
|
|
20
|
+
];
|
|
21
|
+
|
|
15
22
|
export const Default: Story = {
|
|
16
|
-
render: () =>
|
|
23
|
+
render: () => {
|
|
24
|
+
const rows = elements.map((element) => (
|
|
25
|
+
<Table.Row key={element.name}>
|
|
26
|
+
<Table.Cell>{element.position}</Table.Cell>
|
|
27
|
+
<Table.Cell>{element.name}</Table.Cell>
|
|
28
|
+
<Table.Cell>{element.symbol}</Table.Cell>
|
|
29
|
+
<Table.Cell>{element.mass}</Table.Cell>
|
|
30
|
+
</Table.Row>
|
|
31
|
+
));
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Table.Container>
|
|
35
|
+
<Table>
|
|
36
|
+
<Table.Head>
|
|
37
|
+
<Table.Row>
|
|
38
|
+
<Table.Cell>Element position</Table.Cell>
|
|
39
|
+
<Table.Cell>Element name</Table.Cell>
|
|
40
|
+
<Table.Cell>Symbol</Table.Cell>
|
|
41
|
+
<Table.Cell>Atomic mass</Table.Cell>
|
|
42
|
+
</Table.Row>
|
|
43
|
+
</Table.Head>
|
|
44
|
+
<Table.Body>{rows}</Table.Body>
|
|
45
|
+
</Table>
|
|
46
|
+
</Table.Container>
|
|
47
|
+
);
|
|
48
|
+
},
|
|
17
49
|
};
|
|
@@ -1,9 +1,65 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Table as MuiTable,
|
|
4
|
+
type TableProps as MuiTableProps,
|
|
5
|
+
TableBody as MuiTableBody,
|
|
6
|
+
TableCell as MuiTableCell,
|
|
7
|
+
TableContainer as MuiTableContainer,
|
|
8
|
+
TableHead as MuiTableHead,
|
|
9
|
+
TableRow as MuiTableRow,
|
|
10
|
+
TableFooter as MuiTableFooter,
|
|
11
|
+
TableSortLabel as MuiTableSortLabel,
|
|
12
|
+
} from "@mui/material";
|
|
13
|
+
import {
|
|
14
|
+
filterStylingProps,
|
|
15
|
+
type RecursicaOverStyled,
|
|
16
|
+
} from "../../utils/filterStylingProps";
|
|
2
17
|
import { type RecursicaTableProps } from "@recursica/adapter-common";
|
|
18
|
+
import styles from "./Table.module.css";
|
|
3
19
|
|
|
4
|
-
export type TableProps =
|
|
5
|
-
RecursicaTableProps
|
|
20
|
+
export type TableProps = RecursicaOverStyled<
|
|
21
|
+
MuiTableProps & RecursicaTableProps
|
|
22
|
+
>;
|
|
6
23
|
|
|
7
|
-
|
|
8
|
-
|
|
24
|
+
const TableBase = forwardRef<HTMLTableElement, TableProps>(function Table(
|
|
25
|
+
{ overStyled = false, ...rest },
|
|
26
|
+
ref,
|
|
27
|
+
) {
|
|
28
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
29
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
30
|
+
.className as string | undefined;
|
|
31
|
+
|
|
32
|
+
const rootClass = styles.root;
|
|
33
|
+
const finalClass = classNameProp
|
|
34
|
+
? `${rootClass} ${classNameProp}`
|
|
35
|
+
: rootClass;
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<MuiTable
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={finalClass}
|
|
41
|
+
{...(sanitizedProps as unknown as MuiTableProps)}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
TableBase.displayName = "Table";
|
|
47
|
+
|
|
48
|
+
type TableComponent = typeof TableBase & {
|
|
49
|
+
Body: typeof MuiTableBody;
|
|
50
|
+
Cell: typeof MuiTableCell;
|
|
51
|
+
Container: typeof MuiTableContainer;
|
|
52
|
+
Head: typeof MuiTableHead;
|
|
53
|
+
Row: typeof MuiTableRow;
|
|
54
|
+
Footer: typeof MuiTableFooter;
|
|
55
|
+
SortLabel: typeof MuiTableSortLabel;
|
|
9
56
|
};
|
|
57
|
+
|
|
58
|
+
export const Table = TableBase as TableComponent;
|
|
59
|
+
Table.Body = MuiTableBody;
|
|
60
|
+
Table.Cell = MuiTableCell;
|
|
61
|
+
Table.Container = MuiTableContainer;
|
|
62
|
+
Table.Head = MuiTableHead;
|
|
63
|
+
Table.Row = MuiTableRow;
|
|
64
|
+
Table.Footer = MuiTableFooter;
|
|
65
|
+
Table.SortLabel = MuiTableSortLabel;
|
|
@@ -13,7 +13,11 @@ import styles from "./Tabs.module.css";
|
|
|
13
13
|
|
|
14
14
|
import { type RecursicaTabsProps } from "@recursica/adapter-common";
|
|
15
15
|
|
|
16
|
-
export
|
|
16
|
+
export interface RecursicaTabsPropsExtended
|
|
17
|
+
extends Omit<MuiTabsProps, "variant">,
|
|
18
|
+
RecursicaTabsProps {}
|
|
19
|
+
|
|
20
|
+
export type TabsProps = RecursicaOverStyled<RecursicaTabsPropsExtended>;
|
|
17
21
|
|
|
18
22
|
export const Tabs = forwardRef<HTMLDivElement, TabsProps>(
|
|
19
23
|
function Tabs(props, ref) {
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import { type TypographyProps as MuiTypographyProps } from "@mui/material";
|
|
2
3
|
import { Typography } from "../Typography/Typography";
|
|
3
4
|
import { type RecursicaOverStyled } from "../../utils/filterStylingProps";
|
|
4
5
|
import { type RecursicaTextProps } from "@recursica/adapter-common";
|
|
5
6
|
|
|
6
|
-
export type TextProps = RecursicaOverStyled<
|
|
7
|
+
export type TextProps = RecursicaOverStyled<
|
|
8
|
+
Omit<MuiTypographyProps, "variant" | "classes"> & RecursicaTextProps
|
|
9
|
+
>;
|
|
7
10
|
|
|
8
11
|
export const Text = forwardRef<HTMLElement, TextProps>(function Text(
|
|
9
12
|
{ variant = "body", ...rest },
|
|
@@ -18,18 +18,18 @@ import { type RecursicaTextAreaProps as BaseRecursicaTextAreaProps } from "@recu
|
|
|
18
18
|
export interface RecursicaTextAreaProps
|
|
19
19
|
extends Omit<
|
|
20
20
|
MuiTextareaProps,
|
|
21
|
-
|
|
21
|
+
| keyof React.HTMLAttributes<HTMLDivElement>
|
|
22
|
+
| "size"
|
|
23
|
+
| "variant"
|
|
24
|
+
| "radius"
|
|
25
|
+
| "wrapperProps"
|
|
26
|
+
| "maxRows"
|
|
27
|
+
| "minRows"
|
|
28
|
+
| "classes"
|
|
22
29
|
>,
|
|
23
|
-
|
|
30
|
+
Omit<
|
|
24
31
|
RecursicaFormControlWrapperProps,
|
|
25
|
-
| "
|
|
26
|
-
| "assistiveWithIcon"
|
|
27
|
-
| "formLayout"
|
|
28
|
-
| "labelSize"
|
|
29
|
-
| "labelAlignment"
|
|
30
|
-
| "labelOptionalText"
|
|
31
|
-
| "labelWithEditIcon"
|
|
32
|
-
| "onLabelEditClick"
|
|
32
|
+
"controlMaxWidth" | "controlMinWidth"
|
|
33
33
|
>,
|
|
34
34
|
ReadOnlyControlProps,
|
|
35
35
|
BaseRecursicaTextAreaProps {}
|
|
@@ -129,6 +129,7 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
|
|
|
129
129
|
/* Naked Input execution safely decoupled from Mui's macro Input.Wrapper DOM hooks */
|
|
130
130
|
<MuiTextarea
|
|
131
131
|
multiline
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
132
133
|
inputRef={ref as any}
|
|
133
134
|
classes={mergedClassNames}
|
|
134
135
|
disabled={disabled}
|
|
@@ -137,7 +137,9 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
137
137
|
required={required}
|
|
138
138
|
id={id}
|
|
139
139
|
readOnly={readOnly}
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
141
|
readOnlyComponent={readOnlyComponent as any}
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
141
143
|
emptyValueComponent={(emptyValueComponent as any) || undefined}
|
|
142
144
|
readOnlyType="text"
|
|
143
145
|
readOnlyValue={value !== undefined ? value : defaultValue}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import React, { forwardRef } from "react";
|
|
2
|
+
import { type TypographyProps as MuiTypographyProps } from "@mui/material";
|
|
2
3
|
import { Typography } from "../Typography/Typography";
|
|
3
4
|
import { type RecursicaOverStyled } from "../../utils/filterStylingProps";
|
|
4
5
|
import { type RecursicaTitleProps } from "@recursica/adapter-common";
|
|
5
6
|
|
|
6
|
-
export type TitleProps = RecursicaOverStyled<
|
|
7
|
+
export type TitleProps = RecursicaOverStyled<
|
|
8
|
+
Omit<MuiTypographyProps, "variant" | "classes"> & RecursicaTitleProps
|
|
9
|
+
>;
|
|
7
10
|
|
|
8
11
|
export const Title = forwardRef<HTMLElement, TitleProps>(function Title(
|
|
9
12
|
{ order = 1, component, ...rest },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Typography";
|
package/src/components/index.ts
CHANGED