@recursica/mui-adapter 0.28.0 → 0.30.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 +29 -0
- package/dist/index.d.ts +105 -49
- package/dist/mui-adapter.cjs +62 -62
- package/dist/mui-adapter.cjs.map +1 -1
- package/dist/mui-adapter.css +1 -1
- package/dist/mui-adapter.js +6693 -6674
- package/dist/mui-adapter.js.map +1 -1
- package/package.json +3 -3
- package/src/components/Accordion/Accordion.tsx +6 -1
- package/src/components/Checkbox/CheckboxGroup.tsx +5 -3
- package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +3 -3
- package/src/components/Chip/Chip.module.css +5 -5
- package/src/components/Chip/Chip.stories.tsx +2 -2
- package/src/components/Chip/Chip.tsx +20 -19
- package/src/components/Chip/USAGE.md +4 -4
- package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +5 -3
- package/src/components/FileInput/FileInput.stories.tsx +3 -0
- package/src/components/FileInput/FileInput.tsx +11 -10
- package/src/components/FileInput/USAGE.md +1 -0
- package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +6 -6
- package/src/components/FileUpload/FileUpload.tsx +9 -9
- package/src/components/Link/Link.module.css +4 -0
- package/src/components/Radio/RadioGroup.stories.tsx +4 -4
- package/src/components/Radio/RadioGroup.tsx +1 -12
- package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +8 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +17 -28
- package/src/components/SegmentedControl/SegmentedControl.tsx +15 -17
- package/src/components/SegmentedControl/USAGE.md +13 -0
- package/src/components/Switch/SwitchGroup.tsx +5 -1
- package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +64 -0
- package/src/components/Table/Table.module.css +443 -2
- package/src/components/Table/Table.stories.tsx +105 -0
- package/src/components/Table/Table.tsx +62 -5
- package/src/components/Table/USAGE.md +55 -16
|
@@ -47,3 +47,108 @@ export const Default: Story = {
|
|
|
47
47
|
);
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
|
+
|
|
51
|
+
export const SortedColumn: Story = {
|
|
52
|
+
render: () => {
|
|
53
|
+
const sorted = [...elements].sort((a, b) => a.mass - b.mass);
|
|
54
|
+
const rows = sorted.map((element) => (
|
|
55
|
+
<Table.Row key={element.name}>
|
|
56
|
+
<Table.Cell>{element.position}</Table.Cell>
|
|
57
|
+
<Table.Cell>{element.name}</Table.Cell>
|
|
58
|
+
<Table.Cell>{element.symbol}</Table.Cell>
|
|
59
|
+
<Table.Cell>{element.mass}</Table.Cell>
|
|
60
|
+
</Table.Row>
|
|
61
|
+
));
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Table.Container>
|
|
65
|
+
<Table>
|
|
66
|
+
<Table.Head>
|
|
67
|
+
<Table.Row>
|
|
68
|
+
<Table.Cell>Element position</Table.Cell>
|
|
69
|
+
<Table.Cell>Element name</Table.Cell>
|
|
70
|
+
<Table.Cell>Symbol</Table.Cell>
|
|
71
|
+
<Table.Cell sorted="asc">
|
|
72
|
+
<Table.SortLabel active direction="asc">
|
|
73
|
+
Atomic mass
|
|
74
|
+
</Table.SortLabel>
|
|
75
|
+
</Table.Cell>
|
|
76
|
+
</Table.Row>
|
|
77
|
+
</Table.Head>
|
|
78
|
+
<Table.Body>{rows}</Table.Body>
|
|
79
|
+
</Table>
|
|
80
|
+
</Table.Container>
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const SelectedAndDisabledRows: Story = {
|
|
86
|
+
render: () => (
|
|
87
|
+
<Table.Container>
|
|
88
|
+
<Table>
|
|
89
|
+
<Table.Head>
|
|
90
|
+
<Table.Row>
|
|
91
|
+
<Table.Cell>Element position</Table.Cell>
|
|
92
|
+
<Table.Cell>Element name</Table.Cell>
|
|
93
|
+
<Table.Cell>Symbol</Table.Cell>
|
|
94
|
+
<Table.Cell>Atomic mass</Table.Cell>
|
|
95
|
+
</Table.Row>
|
|
96
|
+
</Table.Head>
|
|
97
|
+
<Table.Body>
|
|
98
|
+
{elements.map((element, index) => (
|
|
99
|
+
<Table.Row
|
|
100
|
+
key={element.name}
|
|
101
|
+
selected={index === 0}
|
|
102
|
+
disabled={index === elements.length - 1}
|
|
103
|
+
>
|
|
104
|
+
<Table.Cell>{element.position}</Table.Cell>
|
|
105
|
+
<Table.Cell>{element.name}</Table.Cell>
|
|
106
|
+
<Table.Cell>{element.symbol}</Table.Cell>
|
|
107
|
+
<Table.Cell>{element.mass}</Table.Cell>
|
|
108
|
+
</Table.Row>
|
|
109
|
+
))}
|
|
110
|
+
</Table.Body>
|
|
111
|
+
</Table>
|
|
112
|
+
</Table.Container>
|
|
113
|
+
),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const CurrencyColumnWithFooter: Story = {
|
|
117
|
+
render: () => {
|
|
118
|
+
const prices = [
|
|
119
|
+
{ item: "Widget", price: 19.99 },
|
|
120
|
+
{ item: "Gadget", price: 49.5 },
|
|
121
|
+
{ item: "Gizmo", price: 9.25 },
|
|
122
|
+
];
|
|
123
|
+
const total = prices.reduce((sum, row) => sum + row.price, 0);
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<Table.Container>
|
|
127
|
+
<Table>
|
|
128
|
+
<Table.Head>
|
|
129
|
+
<Table.Row>
|
|
130
|
+
<Table.Cell>Item</Table.Cell>
|
|
131
|
+
<Table.Cell>Price</Table.Cell>
|
|
132
|
+
</Table.Row>
|
|
133
|
+
</Table.Head>
|
|
134
|
+
<Table.Body>
|
|
135
|
+
{prices.map((row) => (
|
|
136
|
+
<Table.Row key={row.item}>
|
|
137
|
+
<Table.Cell>{row.item}</Table.Cell>
|
|
138
|
+
<Table.Cell variant="currency">
|
|
139
|
+
${row.price.toFixed(2)}
|
|
140
|
+
</Table.Cell>
|
|
141
|
+
</Table.Row>
|
|
142
|
+
))}
|
|
143
|
+
</Table.Body>
|
|
144
|
+
<Table.Footer>
|
|
145
|
+
<Table.Row>
|
|
146
|
+
<Table.Cell>Total</Table.Cell>
|
|
147
|
+
<Table.Cell variant="currency">${total.toFixed(2)}</Table.Cell>
|
|
148
|
+
</Table.Row>
|
|
149
|
+
</Table.Footer>
|
|
150
|
+
</Table>
|
|
151
|
+
</Table.Container>
|
|
152
|
+
);
|
|
153
|
+
},
|
|
154
|
+
};
|
|
@@ -21,9 +21,19 @@ import {
|
|
|
21
21
|
filterStylingProps,
|
|
22
22
|
type RecursicaOverStyled,
|
|
23
23
|
} from "../../utils/filterStylingProps";
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
type RecursicaTableProps,
|
|
26
|
+
type RecursicaTableRowProps,
|
|
27
|
+
type RecursicaTableHeaderCellProps,
|
|
28
|
+
type RecursicaTableCellProps,
|
|
29
|
+
} from "@recursica/adapter-common";
|
|
25
30
|
import styles from "./Table.module.css";
|
|
26
31
|
|
|
32
|
+
/** Merges a Recursica-controlled `className` with a caller-supplied one, same idiom as `TableBase`. */
|
|
33
|
+
function withRootClass(rootClass: string, classNameProp: string | undefined) {
|
|
34
|
+
return classNameProp ? `${rootClass} ${classNameProp}` : rootClass;
|
|
35
|
+
}
|
|
36
|
+
|
|
27
37
|
export type TableProps = RecursicaOverStyled<
|
|
28
38
|
MuiTableProps & RecursicaTableProps
|
|
29
39
|
>;
|
|
@@ -72,17 +82,50 @@ export const TableBodyComponent = forwardRef<
|
|
|
72
82
|
});
|
|
73
83
|
TableBodyComponent.displayName = "TableBody";
|
|
74
84
|
|
|
75
|
-
|
|
85
|
+
// MUI's `TableCell` is the single primitive used for header, body, and footer cells alike — it
|
|
86
|
+
// auto-detects which one it is (and whether to render a `<th>` or `<td>`) from its ancestor
|
|
87
|
+
// (`Table.Head`/`Table.Body`/`Table.Footer`). Recursica mirrors that: one cell component whose
|
|
88
|
+
// props cover both the header-only concern (`sorted`) and the body/footer concern (`variant`).
|
|
89
|
+
export type TableCellPropsRecursica = RecursicaOverStyled<
|
|
90
|
+
// MUI's own `variant` ('head' | 'body' | 'footer') is superseded by Recursica's `variant`
|
|
91
|
+
// ('default' | 'currency') — MUI still auto-detects head/body/footer from ancestor context
|
|
92
|
+
// when its native `variant` prop is omitted, so nothing is lost by dropping it here.
|
|
93
|
+
Omit<MuiTableCellProps, "children" | "variant"> &
|
|
94
|
+
RecursicaTableHeaderCellProps &
|
|
95
|
+
RecursicaTableCellProps
|
|
96
|
+
>;
|
|
76
97
|
|
|
77
98
|
export const TableCellComponent = forwardRef<
|
|
78
99
|
HTMLTableCellElement,
|
|
79
100
|
TableCellPropsRecursica
|
|
80
|
-
>(function TableCell(
|
|
101
|
+
>(function TableCell(
|
|
102
|
+
{
|
|
103
|
+
overStyled = false,
|
|
104
|
+
sorted = false,
|
|
105
|
+
disabled = false,
|
|
106
|
+
variant = "default",
|
|
107
|
+
...rest
|
|
108
|
+
},
|
|
109
|
+
ref,
|
|
110
|
+
) {
|
|
81
111
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
112
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
113
|
+
.className as string | undefined;
|
|
82
114
|
return (
|
|
83
115
|
<MuiTableCell
|
|
84
116
|
ref={ref}
|
|
85
117
|
{...(sanitizedProps as unknown as MuiTableCellProps)}
|
|
118
|
+
className={withRootClass(styles.cell, classNameProp)}
|
|
119
|
+
data-sorted={sorted ? "true" : undefined}
|
|
120
|
+
data-disabled={disabled ? "true" : undefined}
|
|
121
|
+
data-currency={variant === "currency" ? "true" : undefined}
|
|
122
|
+
aria-sort={
|
|
123
|
+
sorted === "asc"
|
|
124
|
+
? "ascending"
|
|
125
|
+
: sorted === "desc"
|
|
126
|
+
? "descending"
|
|
127
|
+
: undefined
|
|
128
|
+
}
|
|
86
129
|
/>
|
|
87
130
|
);
|
|
88
131
|
});
|
|
@@ -121,17 +164,28 @@ export const TableHeadComponent = forwardRef<
|
|
|
121
164
|
});
|
|
122
165
|
TableHeadComponent.displayName = "TableHead";
|
|
123
166
|
|
|
124
|
-
export type TableRowPropsRecursica = RecursicaOverStyled<
|
|
167
|
+
export type TableRowPropsRecursica = RecursicaOverStyled<
|
|
168
|
+
Omit<MuiTableRowProps, "children"> & RecursicaTableRowProps
|
|
169
|
+
>;
|
|
125
170
|
|
|
126
171
|
export const TableRowComponent = forwardRef<
|
|
127
172
|
HTMLTableRowElement,
|
|
128
173
|
TableRowPropsRecursica
|
|
129
|
-
>(function TableRow(
|
|
174
|
+
>(function TableRow(
|
|
175
|
+
{ overStyled = false, selected = false, disabled = false, ...rest },
|
|
176
|
+
ref,
|
|
177
|
+
) {
|
|
130
178
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
179
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
180
|
+
.className as string | undefined;
|
|
131
181
|
return (
|
|
132
182
|
<MuiTableRow
|
|
133
183
|
ref={ref}
|
|
134
184
|
{...(sanitizedProps as unknown as MuiTableRowProps)}
|
|
185
|
+
className={withRootClass(styles.row, classNameProp)}
|
|
186
|
+
selected={selected}
|
|
187
|
+
data-selected={selected ? "true" : undefined}
|
|
188
|
+
data-disabled={disabled ? "true" : undefined}
|
|
135
189
|
/>
|
|
136
190
|
);
|
|
137
191
|
});
|
|
@@ -162,10 +216,13 @@ export const TableSortLabelComponent = forwardRef<
|
|
|
162
216
|
TableSortLabelPropsRecursica
|
|
163
217
|
>(function TableSortLabel({ overStyled = false, ...rest }, ref) {
|
|
164
218
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
219
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
220
|
+
.className as string | undefined;
|
|
165
221
|
return (
|
|
166
222
|
<MuiTableSortLabel
|
|
167
223
|
ref={ref}
|
|
168
224
|
{...(sanitizedProps as unknown as MuiTableSortLabelProps)}
|
|
225
|
+
className={withRootClass(styles.sortLabel, classNameProp)}
|
|
169
226
|
/>
|
|
170
227
|
);
|
|
171
228
|
});
|
|
@@ -15,32 +15,71 @@ import { Table } from "@recursica/mui-adapter";
|
|
|
15
15
|
## 2. Basic Example
|
|
16
16
|
|
|
17
17
|
```tsx
|
|
18
|
-
import React from
|
|
18
|
+
import React from "react";
|
|
19
19
|
import { Table } from "@recursica/mui-adapter";
|
|
20
20
|
|
|
21
21
|
export default function Demo() {
|
|
22
22
|
return (
|
|
23
|
-
<Table>
|
|
24
|
-
<Table
|
|
25
|
-
<Table.
|
|
26
|
-
<Table.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<Table.
|
|
32
|
-
<Table.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
<Table.Container>
|
|
24
|
+
<Table>
|
|
25
|
+
<Table.Head>
|
|
26
|
+
<Table.Row>
|
|
27
|
+
<Table.Cell>Name</Table.Cell>
|
|
28
|
+
<Table.Cell>Email</Table.Cell>
|
|
29
|
+
</Table.Row>
|
|
30
|
+
</Table.Head>
|
|
31
|
+
<Table.Body>
|
|
32
|
+
<Table.Row>
|
|
33
|
+
<Table.Cell>Jane Doe</Table.Cell>
|
|
34
|
+
<Table.Cell>jane@example.com</Table.Cell>
|
|
35
|
+
</Table.Row>
|
|
36
|
+
</Table.Body>
|
|
37
|
+
</Table>
|
|
38
|
+
</Table.Container>
|
|
37
39
|
);
|
|
38
40
|
}
|
|
39
41
|
```
|
|
40
42
|
|
|
41
43
|
---
|
|
42
44
|
|
|
43
|
-
## 3.
|
|
45
|
+
## 3. Row and Cell States
|
|
46
|
+
|
|
47
|
+
- **`Table.Row`**: `selected` applies the selected-row background (and MUI's own `selected`/`aria-selected`); `disabled` dims the row and applies the disabled cell colors to every cell in it.
|
|
48
|
+
- **`Table.Cell`**: `sorted="asc" | "desc"` applies the sorted header style (pair with `Table.SortLabel` for the actual sort icon — see below); `variant="currency"` applies the currency text style; `disabled` dims the cell.
|
|
49
|
+
- **`Table.SortLabel`** (wraps MUI's `TableSortLabel`): renders the actual sort arrow. Compose it inside a `Table.Cell` the same way MUI's own docs do.
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
<Table.Head>
|
|
53
|
+
<Table.Row>
|
|
54
|
+
<Table.Cell>Name</Table.Cell>
|
|
55
|
+
<Table.Cell sorted="asc">
|
|
56
|
+
<Table.SortLabel active direction="asc">
|
|
57
|
+
Balance
|
|
58
|
+
</Table.SortLabel>
|
|
59
|
+
</Table.Cell>
|
|
60
|
+
</Table.Row>
|
|
61
|
+
</Table.Head>
|
|
62
|
+
<Table.Body>
|
|
63
|
+
<Table.Row selected>
|
|
64
|
+
<Table.Cell>Jane Doe</Table.Cell>
|
|
65
|
+
<Table.Cell variant="currency">$1,204.50</Table.Cell>
|
|
66
|
+
</Table.Row>
|
|
67
|
+
<Table.Row disabled>
|
|
68
|
+
<Table.Cell>Inactive Account</Table.Cell>
|
|
69
|
+
<Table.Cell variant="currency">$0.00</Table.Cell>
|
|
70
|
+
</Table.Row>
|
|
71
|
+
</Table.Body>
|
|
72
|
+
<Table.Footer>
|
|
73
|
+
<Table.Row>
|
|
74
|
+
<Table.Cell>Total</Table.Cell>
|
|
75
|
+
<Table.Cell variant="currency">$1,204.50</Table.Cell>
|
|
76
|
+
</Table.Row>
|
|
77
|
+
</Table.Footer>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 4. Design System Integration
|
|
44
83
|
|
|
45
84
|
All Recursica components in the `@recursica/mui-adapter` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
46
85
|
|