@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.
Files changed (34) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/index.d.ts +105 -49
  3. package/dist/mui-adapter.cjs +62 -62
  4. package/dist/mui-adapter.cjs.map +1 -1
  5. package/dist/mui-adapter.css +1 -1
  6. package/dist/mui-adapter.js +6693 -6674
  7. package/dist/mui-adapter.js.map +1 -1
  8. package/package.json +3 -3
  9. package/src/components/Accordion/Accordion.tsx +6 -1
  10. package/src/components/Checkbox/CheckboxGroup.tsx +5 -3
  11. package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +3 -3
  12. package/src/components/Chip/Chip.module.css +5 -5
  13. package/src/components/Chip/Chip.stories.tsx +2 -2
  14. package/src/components/Chip/Chip.tsx +20 -19
  15. package/src/components/Chip/USAGE.md +4 -4
  16. package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +5 -3
  17. package/src/components/FileInput/FileInput.stories.tsx +3 -0
  18. package/src/components/FileInput/FileInput.tsx +11 -10
  19. package/src/components/FileInput/USAGE.md +1 -0
  20. package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +6 -6
  21. package/src/components/FileUpload/FileUpload.tsx +9 -9
  22. package/src/components/Link/Link.module.css +4 -0
  23. package/src/components/Radio/RadioGroup.stories.tsx +4 -4
  24. package/src/components/Radio/RadioGroup.tsx +1 -12
  25. package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +8 -0
  26. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +17 -28
  27. package/src/components/SegmentedControl/SegmentedControl.tsx +15 -17
  28. package/src/components/SegmentedControl/USAGE.md +13 -0
  29. package/src/components/Switch/SwitchGroup.tsx +5 -1
  30. package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +64 -0
  31. package/src/components/Table/Table.module.css +443 -2
  32. package/src/components/Table/Table.stories.tsx +105 -0
  33. package/src/components/Table/Table.tsx +62 -5
  34. 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 { type RecursicaTableProps } from "@recursica/adapter-common";
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
- export type TableCellPropsRecursica = RecursicaOverStyled<MuiTableCellProps>;
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({ overStyled = false, ...rest }, ref) {
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<MuiTableRowProps>;
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({ overStyled = false, ...rest }, ref) {
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 'react';
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.Thead>
25
- <Table.Tr>
26
- <Table.Th>Name</Table.Th>
27
- <Table.Th>Email</Table.Tr>
28
- </Table.Tr>
29
- </Table.Thead>
30
- <Table.Tbody>
31
- <Table.Tr>
32
- <Table.Td>Jane Doe</Table.Tr>
33
- <Table.Td>jane@example.com</Table.Tr>
34
- </Table.Tr>
35
- </Table.Tbody>
36
- </Table>
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. Design System Integration
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