@recursica/mui-adapter 0.29.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.
@@ -6,7 +6,6 @@ import {
6
6
  } from "@mui/material";
7
7
  import {
8
8
  filterStylingProps,
9
- omitUnsupportedProps,
10
9
  mergeClassNames,
11
10
  type RecursicaOverStyled,
12
11
  } from "../../utils/filterStylingProps";
@@ -23,9 +22,7 @@ export type SegmentedControlProps = RecursicaOverStyled<
23
22
  | "color"
24
23
  | "classNames"
25
24
  | "className"
26
- | "disabled"
27
25
  | "value"
28
- | "onChange"
29
26
  > & {
30
27
  className?: string;
31
28
  classNames?: Partial<Record<string, string>>;
@@ -61,21 +58,13 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
61
58
  fullWidth,
62
59
  data = [],
63
60
  value,
61
+ disabled,
64
62
  onChange,
65
63
  ...rest
66
64
  },
67
65
  ref,
68
66
  ) {
69
- // Props this component intentionally doesn't support — deleted at runtime so they can't leak
70
- // through even if a caller forces them via plain JavaScript, bypassing the Omit<> above.
71
- const UNSUPPORTED_PROPS = [
72
- "disabled", // Recursica controls per-item disabled state via `data.disabled`, not the group
73
- ] as const satisfies readonly (keyof MuiSegmentedControlProps)[];
74
-
75
- const sanitizedProps = omitUnsupportedProps(
76
- filterStylingProps(rest, overStyled),
77
- UNSUPPORTED_PROPS,
78
- );
67
+ const sanitizedProps = filterStylingProps(rest, overStyled);
79
68
  const restRecord = sanitizedProps as Record<string, unknown>;
80
69
 
81
70
  const stylingParams = useSegmentedControlClassNames(restRecord);
@@ -94,12 +83,12 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
94
83
  const activeValue = value !== undefined ? value : uncontrolledValue;
95
84
 
96
85
  const handleChange = (
97
- _event: React.MouseEvent<HTMLElement>,
86
+ event: React.MouseEvent<HTMLElement>,
98
87
  newValue: string | null,
99
88
  ) => {
100
89
  if (newValue !== null) {
101
90
  setUncontrolledValue(newValue);
102
- onChange?.(newValue);
91
+ onChange?.(event, newValue);
103
92
  }
104
93
  };
105
94
 
@@ -116,6 +105,7 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
116
105
  fullWidth={fullWidth}
117
106
  data-orientation={orientation}
118
107
  exclusive
108
+ disabled={disabled}
119
109
  value={activeValue}
120
110
  onChange={
121
111
  handleChange as React.ComponentProps<
@@ -126,7 +116,12 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
126
116
  {data.map((item) => {
127
117
  const itemValue = typeof item === "string" ? item : item.value;
128
118
  const itemLabel = typeof item === "string" ? item : item.label;
129
- const itemDisabled = typeof item === "string" ? false : item.disabled;
119
+ // `undefined` (not `false`) for items with no per-item override, so the group-level
120
+ // `disabled` above can cascade through MUI's ToggleButtonGroupContext instead of being
121
+ // masked by an explicit `false` on every ToggleButton.
122
+ const itemDisabled =
123
+ typeof item === "string" ? undefined : item.disabled;
124
+ const itemIcon = typeof item === "string" ? undefined : item.icon;
130
125
 
131
126
  return (
132
127
  <ToggleButton
@@ -135,7 +130,10 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
135
130
  disabled={itemDisabled}
136
131
  className={stylingParams.classNames.control}
137
132
  >
138
- <div className={stylingParams.classNames.label}>{itemLabel}</div>
133
+ <div className={stylingParams.classNames.label}>
134
+ {itemIcon}
135
+ {itemLabel}
136
+ </div>
139
137
  </ToggleButton>
140
138
  );
141
139
  })}
@@ -23,6 +23,17 @@ export default function Demo() {
23
23
  }
24
24
  ```
25
25
 
26
+ Each `data` item may also be an object with an optional `icon`, rendered ahead of the label:
27
+
28
+ ```tsx
29
+ <SegmentedControl
30
+ data={[
31
+ { value: "daily", label: "Daily", icon: <CheckIcon /> },
32
+ { value: "weekly", label: "Weekly" },
33
+ ]}
34
+ />
35
+ ```
36
+
26
37
  ---
27
38
 
28
39
  ## 3. Design System Integration
@@ -34,3 +45,5 @@ All Recursica components in the `@recursica/mui-adapter` package adhere strictly
34
45
  > - **Anti-override protection**: Rogues style injections (like inline `style` or arbitrary `className`) are automatically blocked by our prop layer unless `overStyled={true}` is explicitly provided.
35
46
  > - **No Direct Layers**: Do not pass a `layer` prop to this component. To place it on a specific visual layer, wrap it in a `<Layer layer={0|1|2|3}>` component natively.
36
47
  > - **Variables and Theming**: Styling is entirely determined by local CSS variables defined in `recursica_variables_scoped.css` and mapped in the component's CSS module.
48
+
49
+ A top-level `disabled` disables every item at once; an individual item can still be disabled on its own via `data[].disabled`.
@@ -43,7 +43,11 @@ export interface RecursicaSwitchGroupProps
43
43
  | "defaultValue"
44
44
  >,
45
45
  ReadOnlyControlProps,
46
- BaseRecursicaSwitchGroupProps {}
46
+ BaseRecursicaSwitchGroupProps {
47
+ // MUI has no native switch-group concept to match (its own `FormGroup` is layout-only, no
48
+ // value/onChange) — this signature is Recursica's own, same as TransferList/Accordion/CheckboxGroup.
49
+ onChange?: (value: string[]) => void;
50
+ }
47
51
 
48
52
  export type SwitchGroupProps = RecursicaOverStyled<RecursicaSwitchGroupProps>;
49
53