@recursica/mantine-adapter 0.42.0 → 0.43.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 +18 -0
- package/dist/index.d.ts +93 -15
- package/dist/mantine-adapter.cjs +2 -2
- package/dist/mantine-adapter.cjs.map +1 -1
- package/dist/mantine-adapter.css +1 -1
- package/dist/mantine-adapter.js +3546 -3250
- package/dist/mantine-adapter.js.map +1 -1
- package/package.json +1 -1
- package/src/GlobalExemptions.modules.css +0 -6
- package/src/components/Accordion/Accordion.module.css +0 -8
- package/src/components/Accordion/Accordion.tsx +32 -33
- package/src/components/AssistiveElement/AssistiveElement.tsx +1 -1
- package/src/components/AutoComplete/AutoComplete.module.css +0 -7
- package/src/components/AutoComplete/AutoComplete.tsx +26 -38
- package/src/components/Avatar/Avatar.module.css +0 -8
- package/src/components/Avatar/Avatar.tsx +22 -23
- package/src/components/Badge/Badge.tsx +12 -18
- package/src/components/Breadcrumb/Breadcrumb.tsx +10 -18
- package/src/components/Button/Button.tsx +31 -30
- package/src/components/Card/Card.tsx +48 -27
- package/src/components/Checkbox/Checkbox.tsx +29 -42
- package/src/components/Checkbox/CheckboxGroup.tsx +12 -5
- package/src/components/Chip/Chip.module.css +0 -16
- package/src/components/Chip/Chip.tsx +34 -27
- package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +14 -1
- package/src/components/DatePicker/DatePicker.icons.tsx +27 -0
- package/src/components/DatePicker/DatePicker.module.css +256 -7
- package/src/components/DatePicker/DatePicker.stories.tsx +0 -7
- package/src/components/DatePicker/DatePicker.tsx +68 -33
- package/src/components/DatePicker/USAGE.md +6 -2
- package/src/components/Dropdown/BareDropdown.tsx +25 -13
- package/src/components/Dropdown/Dropdown.module.css +0 -7
- package/src/components/Dropdown/Dropdown.tsx +25 -38
- package/src/components/FileInput/FileInput.module.css +0 -21
- package/src/components/FileInput/FileInput.tsx +1 -1
- package/src/components/FileUpload/FileUpload.module.css +0 -11
- package/src/components/FileUpload/FileUpload.tsx +1 -1
- package/src/components/HoverCard/HoverCard.module.css +1 -7
- package/src/components/HoverCard/HoverCard.tsx +18 -34
- package/src/components/Label/Label.module.css +0 -6
- package/src/components/Label/Label.tsx +20 -21
- package/src/components/Link/Link.module.css +1 -6
- package/src/components/Link/Link.tsx +6 -14
- package/src/components/Loader/Loader.tsx +8 -16
- package/src/components/Menu/Menu.module.css +0 -6
- package/src/components/Menu/Menu.tsx +55 -48
- package/src/components/Modal/Modal.module.css +0 -11
- package/src/components/Modal/Modal.tsx +134 -96
- package/src/components/NumberInput/NumberInput.module.css +0 -7
- package/src/components/NumberInput/NumberInput.tsx +14 -7
- package/src/components/Pagination/Pagination.module.css +0 -81
- package/src/components/Pagination/Pagination.tsx +25 -34
- package/src/components/Panel/Panel.tsx +19 -26
- package/src/components/Popover/Popover.tsx +19 -31
- package/src/components/Radio/Radio.tsx +32 -43
- package/src/components/Radio/RadioGroup.tsx +11 -4
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +1 -1
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +1 -1
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +1 -1
- package/src/components/SegmentedControl/SegmentedControl.module.css +0 -1
- package/src/components/SegmentedControl/SegmentedControl.tsx +29 -33
- package/src/components/Slider/Slider.tsx +30 -43
- package/src/components/Stepper/Stepper.tsx +20 -13
- package/src/components/Switch/Switch.tsx +45 -45
- package/src/components/Switch/SwitchGroup.tsx +11 -4
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +13 -6
- package/src/components/Text/Text.tsx +1 -1
- package/src/components/TextArea/TextArea.module.css +0 -7
- package/src/components/TextArea/TextArea.tsx +21 -25
- package/src/components/TextField/TextField.module.css +0 -7
- package/src/components/TextField/TextField.tsx +23 -30
- package/src/components/TimePicker/TimePicker.module.css +0 -16
- package/src/components/TimePicker/TimePicker.tsx +26 -12
- package/src/components/Timeline/Timeline.module.css +0 -6
- package/src/components/Timeline/Timeline.tsx +7 -21
- package/src/components/Timeline/TimelineItem.tsx +14 -26
- package/src/components/Title/Title.tsx +12 -2
- package/src/components/Toast/Toast.module.css +0 -7
- package/src/components/Toast/Toast.tsx +32 -31
- package/src/components/Tooltip/Tooltip.module.css +0 -9
- package/src/components/Tooltip/Tooltip.tsx +18 -34
- package/src/components/TransferList/TransferList.module.css +0 -8
- package/src/components/TransferList/TransferList.tsx +1 -1
- package/src/components/Tree/Tree.tsx +8 -8
- package/src/utils/filterStylingProps.ts +4 -0
package/package.json
CHANGED
|
@@ -5,9 +5,3 @@
|
|
|
5
5
|
* recursica_variables_scoped.css but are not used by any specific component.
|
|
6
6
|
* Isolating them here keeps individual component stylesheets clean and focused.
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
/* ==== GLOBAL ICON STYLE ====
|
|
10
|
-
Global layout option specifying the overall SVG rendering style (solid/outline).
|
|
11
|
-
Note to Forge Devs: style is not a CSS property or variable type and cannot be applied in standard CSS stylesheets.
|
|
12
|
-
This variable is ignored in the UI adapters and should be reviewed by the Forge team. */
|
|
13
|
-
/* recursica-ignore: --recursica_ui-kit_globals_icon_style */
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/* EXEMPTIONS:
|
|
2
|
-
- accordion-header open-appearance background-color/border-color are ignored because Forge does
|
|
3
|
-
not apply a visual swap on expand, even though the token schema defines "open" appearance
|
|
4
|
-
colors distinct from "closed" (see .control below, which intentionally keeps a constant
|
|
5
|
-
background/border across collapsed/expanded). */
|
|
6
|
-
/* recursica-ignore: --recursica_ui-kit_components_accordion-header_variants_appearance_open_properties_colors_background-color */
|
|
7
|
-
/* recursica-ignore: --recursica_ui-kit_components_accordion-header_variants_appearance_open_properties_colors_border-color */
|
|
8
|
-
|
|
9
1
|
/* ==== ACCORDION CONTAINER ==== */
|
|
10
2
|
.root {
|
|
11
3
|
box-sizing: border-box;
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
} from "@mantine/core";
|
|
9
9
|
import {
|
|
10
10
|
filterStylingProps,
|
|
11
|
+
omitUnsupportedProps,
|
|
12
|
+
mergeClassNames,
|
|
11
13
|
type RecursicaOverStyled,
|
|
12
14
|
} from "../../utils/filterStylingProps";
|
|
13
15
|
import styles from "./Accordion.module.css";
|
|
@@ -47,44 +49,31 @@ const AccordionBase = function Accordion({
|
|
|
47
49
|
: variant;
|
|
48
50
|
|
|
49
51
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
52
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
50
53
|
|
|
51
54
|
// Bind all deep CSS module references natively into the global class mapping schema
|
|
52
|
-
const mergedClassNames
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
classNamesProp &&
|
|
66
|
-
typeof classNamesProp === "object" &&
|
|
67
|
-
!Array.isArray(classNamesProp)
|
|
68
|
-
) {
|
|
69
|
-
const o = classNamesProp as Record<string, string>;
|
|
70
|
-
Object.keys(o).forEach((key) => {
|
|
71
|
-
if (mergedClassNames[key]) {
|
|
72
|
-
mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
|
|
73
|
-
} else {
|
|
74
|
-
mergedClassNames[key] = o[key];
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
55
|
+
const mergedClassNames = mergeClassNames(
|
|
56
|
+
{
|
|
57
|
+
root: styles.root,
|
|
58
|
+
item: styles.item,
|
|
59
|
+
control: styles.control,
|
|
60
|
+
label: styles.label,
|
|
61
|
+
chevron: styles.chevron,
|
|
62
|
+
icon: styles.icon,
|
|
63
|
+
panel: styles.panel,
|
|
64
|
+
content: styles.content,
|
|
65
|
+
},
|
|
66
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
67
|
+
);
|
|
78
68
|
|
|
79
|
-
const classNameProp =
|
|
80
|
-
.className as string | undefined;
|
|
69
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
81
70
|
|
|
82
71
|
return (
|
|
83
72
|
<MantineAccordion
|
|
73
|
+
{...(sanitizedProps as unknown as MantineAccordionProps)}
|
|
84
74
|
variant={resolvedVariant as MantineAccordionProps["variant"]}
|
|
85
75
|
className={classNameProp}
|
|
86
76
|
classNames={mergedClassNames}
|
|
87
|
-
{...(sanitizedProps as unknown as MantineAccordionProps)}
|
|
88
77
|
/>
|
|
89
78
|
);
|
|
90
79
|
};
|
|
@@ -128,9 +117,9 @@ export const AccordionItem = forwardRef<
|
|
|
128
117
|
return (
|
|
129
118
|
<MantineAccordion.Item
|
|
130
119
|
ref={ref}
|
|
120
|
+
{...(sanitizedProps as unknown as AccordionItemProps)}
|
|
131
121
|
className={finalClass}
|
|
132
122
|
data-disabled={disabled || undefined}
|
|
133
|
-
{...(sanitizedProps as unknown as AccordionItemProps)}
|
|
134
123
|
>
|
|
135
124
|
{title ? (
|
|
136
125
|
<>
|
|
@@ -155,6 +144,13 @@ export type AccordionControlWrapperProps = RecursicaOverStyled<
|
|
|
155
144
|
Omit<AccordionControlProps, "icon"> & RecursicaAccordionControlProps
|
|
156
145
|
>;
|
|
157
146
|
|
|
147
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
148
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
149
|
+
const UNSUPPORTED_PROPS = [
|
|
150
|
+
"icon", // Mantine's native icon slot is fully computed here from `leftIcon`; the `Omit<>` on
|
|
151
|
+
// AccordionControlWrapperProps only stops a well-typed caller, this is the runtime backstop.
|
|
152
|
+
] as const satisfies readonly (keyof AccordionControlProps)[];
|
|
153
|
+
|
|
158
154
|
export const AccordionControl = forwardRef<
|
|
159
155
|
HTMLButtonElement,
|
|
160
156
|
AccordionControlWrapperProps
|
|
@@ -162,13 +158,17 @@ export const AccordionControl = forwardRef<
|
|
|
162
158
|
{ leftIcon, children, overStyled = false, ...rest },
|
|
163
159
|
ref,
|
|
164
160
|
) {
|
|
165
|
-
const sanitizedProps =
|
|
161
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
162
|
+
filterStylingProps(rest, overStyled),
|
|
163
|
+
UNSUPPORTED_PROPS,
|
|
164
|
+
);
|
|
166
165
|
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
167
166
|
.className as string | undefined;
|
|
168
167
|
|
|
169
168
|
return (
|
|
170
169
|
<MantineAccordion.Control
|
|
171
170
|
ref={ref}
|
|
171
|
+
{...(sanitizedProps as unknown as AccordionControlProps)}
|
|
172
172
|
className={classNameProp}
|
|
173
173
|
icon={
|
|
174
174
|
leftIcon ? (
|
|
@@ -177,7 +177,6 @@ export const AccordionControl = forwardRef<
|
|
|
177
177
|
</span>
|
|
178
178
|
) : undefined
|
|
179
179
|
}
|
|
180
|
-
{...(sanitizedProps as unknown as AccordionControlProps)}
|
|
181
180
|
>
|
|
182
181
|
{children}
|
|
183
182
|
</MantineAccordion.Control>
|
|
@@ -201,8 +200,8 @@ export const AccordionPanel = forwardRef<
|
|
|
201
200
|
return (
|
|
202
201
|
<MantineAccordion.Panel
|
|
203
202
|
ref={ref}
|
|
204
|
-
className={classNameProp}
|
|
205
203
|
{...(sanitizedProps as unknown as AccordionPanelProps)}
|
|
204
|
+
className={classNameProp}
|
|
206
205
|
/>
|
|
207
206
|
);
|
|
208
207
|
});
|
|
@@ -74,11 +74,11 @@ export const AssistiveElement = forwardRef<
|
|
|
74
74
|
return (
|
|
75
75
|
<div
|
|
76
76
|
ref={ref}
|
|
77
|
+
{...restRecord} // Spread standard HTML attributes (like id, aria-*) natively.
|
|
77
78
|
className={finalClass}
|
|
78
79
|
data-variant={assistiveVariant}
|
|
79
80
|
role={resolvedRole}
|
|
80
81
|
style={restRecord.style as React.CSSProperties}
|
|
81
|
-
{...restRecord} // Spread standard HTML attributes (like id, aria-*) natively.
|
|
82
82
|
>
|
|
83
83
|
{assistiveWithIcon && (
|
|
84
84
|
<span className={styles.iconWrapper}>
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/* EXEMPTIONS:
|
|
2
|
-
- border-size variables are ignored because the input box uses a uniform static boundary to prevent
|
|
3
|
-
unexpected layout shifts or flickering when switching between focused, disabled, or error states. */
|
|
4
|
-
/* recursica-ignore: --recursica_ui-kit_components_autocomplete_properties_border-size */
|
|
5
|
-
/* recursica-ignore: --recursica_ui-kit_components_autocomplete_variants_states_disabled_properties_border-size */
|
|
6
|
-
/* recursica-ignore: --recursica_ui-kit_components_autocomplete_variants_states_error_properties_border-size */
|
|
7
|
-
|
|
8
1
|
/* LAYOUT SPACING OVERRIDES:
|
|
9
2
|
- Sets the --form-control-margin-bottom spacing hook to map component-specific layout tokens.
|
|
10
3
|
- Also sets the --autocomplete-control-{max,min}-width hooks consumed inline in AutoComplete.tsx,
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
8
8
|
import {
|
|
9
9
|
filterStylingProps,
|
|
10
|
+
omitUnsupportedProps,
|
|
11
|
+
mergeClassNames,
|
|
10
12
|
type RecursicaOverStyled,
|
|
11
13
|
} from "../../utils/filterStylingProps";
|
|
12
14
|
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
@@ -42,6 +44,14 @@ export interface RecursicaAutoCompleteProps
|
|
|
42
44
|
|
|
43
45
|
export type AutoCompleteProps = RecursicaOverStyled<RecursicaAutoCompleteProps>;
|
|
44
46
|
|
|
47
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
48
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
49
|
+
const UNSUPPORTED_PROPS = [
|
|
50
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
51
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
52
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
53
|
+
] as const satisfies readonly (keyof MantineAutocompleteProps)[];
|
|
54
|
+
|
|
45
55
|
export const AutoComplete = forwardRef<HTMLInputElement, AutoCompleteProps>(
|
|
46
56
|
function AutoComplete(props, ref) {
|
|
47
57
|
const {
|
|
@@ -72,46 +82,24 @@ export const AutoComplete = forwardRef<HTMLInputElement, AutoCompleteProps>(
|
|
|
72
82
|
defaultValue,
|
|
73
83
|
...rest
|
|
74
84
|
} = props;
|
|
75
|
-
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
76
|
-
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
77
85
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
87
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
88
|
+
UNSUPPORTED_PROPS,
|
|
89
|
+
);
|
|
90
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
82
91
|
|
|
83
92
|
// Securely map core native blocks down ensuring nested CSS modules map precisely
|
|
84
|
-
const mergedClassNames
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
classNamesProp &&
|
|
95
|
-
typeof classNamesProp === "object" &&
|
|
96
|
-
!Array.isArray(classNamesProp)
|
|
97
|
-
) {
|
|
98
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
99
|
-
mergedClassNames.wrapper = o.wrapper
|
|
100
|
-
? `${styles.root} ${o.wrapper}`
|
|
101
|
-
: styles.root;
|
|
102
|
-
mergedClassNames.input = o.input
|
|
103
|
-
? `${styles.input} ${o.input}`
|
|
104
|
-
: styles.input;
|
|
105
|
-
mergedClassNames.section = o.section
|
|
106
|
-
? `${styles.section} ${o.section}`
|
|
107
|
-
: styles.section;
|
|
108
|
-
mergedClassNames.dropdown = o.dropdown
|
|
109
|
-
? `${styles.dropdown} ${o.dropdown}`
|
|
110
|
-
: styles.dropdown;
|
|
111
|
-
mergedClassNames.option = o.option
|
|
112
|
-
? `${styles.option} ${o.option}`
|
|
113
|
-
: styles.option;
|
|
114
|
-
}
|
|
93
|
+
const mergedClassNames = mergeClassNames(
|
|
94
|
+
{
|
|
95
|
+
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
96
|
+
input: styles.input,
|
|
97
|
+
section: styles.section,
|
|
98
|
+
dropdown: styles.dropdown,
|
|
99
|
+
option: styles.option,
|
|
100
|
+
},
|
|
101
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
102
|
+
);
|
|
115
103
|
|
|
116
104
|
const wrapperClass = className
|
|
117
105
|
? `${styles.layoutOverride} ${className}`
|
|
@@ -147,12 +135,12 @@ export const AutoComplete = forwardRef<HTMLInputElement, AutoCompleteProps>(
|
|
|
147
135
|
/* Naked Input execution safely decoupled from Mantine's macro Input.Wrapper DOM hooks */
|
|
148
136
|
<MantineAutocomplete
|
|
149
137
|
ref={ref}
|
|
138
|
+
{...(sanitizedProps as unknown as MantineAutocompleteProps)}
|
|
150
139
|
classNames={mergedClassNames}
|
|
151
140
|
disabled={disabled}
|
|
152
141
|
value={value as string | undefined}
|
|
153
142
|
defaultValue={defaultValue as string | undefined}
|
|
154
143
|
error={!!error}
|
|
155
|
-
{...(sanitizedProps as unknown as MantineAutocompleteProps)}
|
|
156
144
|
/>
|
|
157
145
|
}
|
|
158
146
|
/>
|
|
@@ -7,14 +7,6 @@ HARDCODED VALUES:
|
|
|
7
7
|
- Image has no explicit size tokens other than root size, assume it scales 100%
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
/* EXEMPTIONS:
|
|
11
|
-
The generic size variables below are defined in Figma but unused.
|
|
12
|
-
We explicitly style the avatar's dimensions using the dedicated width and height tokens
|
|
13
|
-
(e.g., small_properties_width and small_properties_height) for precise component layout. */
|
|
14
|
-
/* recursica-ignore: --recursica_ui-kit_components_avatar_variants_sizes_default_properties_size */
|
|
15
|
-
/* recursica-ignore: --recursica_ui-kit_components_avatar_variants_sizes_large_properties_size */
|
|
16
|
-
/* recursica-ignore: --recursica_ui-kit_components_avatar_variants_sizes_small_properties_size */
|
|
17
|
-
|
|
18
10
|
.root {
|
|
19
11
|
box-sizing: border-box;
|
|
20
12
|
margin: 0;
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
} from "@mantine/core";
|
|
7
7
|
import {
|
|
8
8
|
filterStylingProps,
|
|
9
|
+
omitUnsupportedProps,
|
|
10
|
+
mergeClassNames,
|
|
9
11
|
type RecursicaOverStyled,
|
|
10
12
|
} from "../../utils/filterStylingProps";
|
|
11
13
|
import styles from "./Avatar.module.css";
|
|
@@ -41,7 +43,17 @@ const _Avatar = forwardRef<HTMLDivElement, AvatarProps>(function Avatar(
|
|
|
41
43
|
large: "lg",
|
|
42
44
|
} as const;
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
47
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
48
|
+
const UNSUPPORTED_PROPS = [
|
|
49
|
+
"color", // Colors are token-driven via `data-variant`; Mantine's native palette isn't exposed.
|
|
50
|
+
"radius", // Avatar corner radius is controlled by design tokens, not a raw radius prop.
|
|
51
|
+
] as const satisfies readonly (keyof MantineAvatarProps)[];
|
|
52
|
+
|
|
53
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
54
|
+
filterStylingProps(rest, overStyled),
|
|
55
|
+
UNSUPPORTED_PROPS,
|
|
56
|
+
);
|
|
45
57
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
46
58
|
|
|
47
59
|
// Determine semantic style based on provided props
|
|
@@ -52,33 +64,21 @@ const _Avatar = forwardRef<HTMLDivElement, AvatarProps>(function Avatar(
|
|
|
52
64
|
computedStyle = "icon";
|
|
53
65
|
}
|
|
54
66
|
|
|
55
|
-
const mergedClassNames
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
classNamesProp &&
|
|
64
|
-
typeof classNamesProp === "object" &&
|
|
65
|
-
!Array.isArray(classNamesProp)
|
|
66
|
-
) {
|
|
67
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
68
|
-
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
69
|
-
mergedClassNames.image = o.image
|
|
70
|
-
? `${styles.image} ${o.image}`
|
|
71
|
-
: styles.image;
|
|
72
|
-
mergedClassNames.placeholder = o.placeholder
|
|
73
|
-
? `${styles.placeholder} ${o.placeholder}`
|
|
74
|
-
: styles.placeholder;
|
|
75
|
-
}
|
|
67
|
+
const mergedClassNames = mergeClassNames(
|
|
68
|
+
{
|
|
69
|
+
root: styles.root,
|
|
70
|
+
image: styles.image,
|
|
71
|
+
placeholder: styles.placeholder,
|
|
72
|
+
},
|
|
73
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
74
|
+
);
|
|
76
75
|
|
|
77
76
|
const classNameProp = restRecord.className as string | undefined;
|
|
78
77
|
|
|
79
78
|
return (
|
|
80
79
|
<MantineAvatar
|
|
81
80
|
ref={ref}
|
|
81
|
+
{...sanitizedProps}
|
|
82
82
|
className={classNameProp}
|
|
83
83
|
classNames={mergedClassNames}
|
|
84
84
|
variant={mapVariant[variant]}
|
|
@@ -87,7 +87,6 @@ const _Avatar = forwardRef<HTMLDivElement, AvatarProps>(function Avatar(
|
|
|
87
87
|
data-variant={variant}
|
|
88
88
|
data-size={size}
|
|
89
89
|
data-style={computedStyle}
|
|
90
|
-
{...sanitizedProps}
|
|
91
90
|
>
|
|
92
91
|
{icon != null ? (
|
|
93
92
|
<span className={styles.iconWrapper} aria-hidden>
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "@mantine/core";
|
|
7
7
|
import {
|
|
8
8
|
filterStylingProps,
|
|
9
|
+
mergeClassNames,
|
|
9
10
|
type RecursicaOverStyled,
|
|
10
11
|
} from "../../utils/filterStylingProps";
|
|
11
12
|
import styles from "./Badge.module.css";
|
|
@@ -25,23 +26,16 @@ const _Badge = forwardRef<HTMLDivElement, BadgeProps>(function Badge(
|
|
|
25
26
|
// External layout props like margins are safely preserved.
|
|
26
27
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
27
28
|
|
|
28
|
-
const mergedClassNames
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
!Array.isArray(classNamesProp)
|
|
39
|
-
) {
|
|
40
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
41
|
-
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
42
|
-
mergedClassNames.section = o.section ?? styles.section;
|
|
43
|
-
mergedClassNames.label = o.label ?? styles.label;
|
|
44
|
-
}
|
|
29
|
+
const mergedClassNames = mergeClassNames(
|
|
30
|
+
{
|
|
31
|
+
root: styles.root,
|
|
32
|
+
section: styles.section,
|
|
33
|
+
label: styles.label,
|
|
34
|
+
},
|
|
35
|
+
(sanitizedProps as Record<string, unknown>).classNames as
|
|
36
|
+
| Partial<Record<string, string>>
|
|
37
|
+
| undefined,
|
|
38
|
+
);
|
|
45
39
|
|
|
46
40
|
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
47
41
|
.className as string | undefined;
|
|
@@ -52,9 +46,9 @@ const _Badge = forwardRef<HTMLDivElement, BadgeProps>(function Badge(
|
|
|
52
46
|
return (
|
|
53
47
|
<MantineBadge
|
|
54
48
|
ref={ref}
|
|
49
|
+
{...sanitizedProps}
|
|
55
50
|
variant="filled" // We manage visual style purely through our CSS variables mapping
|
|
56
51
|
data-variant={variant}
|
|
57
|
-
{...sanitizedProps}
|
|
58
52
|
className={finalClass}
|
|
59
53
|
classNames={mergedClassNames}
|
|
60
54
|
/>
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from "@mantine/core";
|
|
6
6
|
import {
|
|
7
7
|
filterStylingProps,
|
|
8
|
+
mergeClassNames,
|
|
8
9
|
type RecursicaOverStyled,
|
|
9
10
|
} from "../../utils/filterStylingProps";
|
|
10
11
|
import styles from "./Breadcrumb.module.css";
|
|
@@ -24,24 +25,15 @@ export const Breadcrumb = forwardRef<HTMLDivElement, BreadcrumbProps>(
|
|
|
24
25
|
overStyled,
|
|
25
26
|
);
|
|
26
27
|
|
|
27
|
-
const mergedClassNames
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
typeof classNamesProp === "object" &&
|
|
37
|
-
!Array.isArray(classNamesProp)
|
|
38
|
-
) {
|
|
39
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
40
|
-
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
41
|
-
mergedClassNames.separator = o.separator
|
|
42
|
-
? `${styles.separator} ${o.separator}`
|
|
43
|
-
: styles.separator;
|
|
44
|
-
}
|
|
28
|
+
const mergedClassNames = mergeClassNames(
|
|
29
|
+
{
|
|
30
|
+
root: styles.root,
|
|
31
|
+
separator: styles.separator,
|
|
32
|
+
},
|
|
33
|
+
(sanitizedProps as Record<string, unknown>).classNames as
|
|
34
|
+
| Partial<Record<string, string>>
|
|
35
|
+
| undefined,
|
|
36
|
+
);
|
|
45
37
|
|
|
46
38
|
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
47
39
|
.className as string | undefined;
|
|
@@ -7,6 +7,9 @@ import {
|
|
|
7
7
|
} from "@mantine/core";
|
|
8
8
|
import {
|
|
9
9
|
filterStylingProps,
|
|
10
|
+
omitUnsupportedProps,
|
|
11
|
+
withCallerOverride,
|
|
12
|
+
mergeClassNames,
|
|
10
13
|
type RecursicaOverStyled,
|
|
11
14
|
} from "../../utils/filterStylingProps";
|
|
12
15
|
import styles from "./Button.module.css";
|
|
@@ -49,11 +52,17 @@ const _Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
|
|
|
49
52
|
small: "sm",
|
|
50
53
|
} as const;
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
56
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
57
|
+
const UNSUPPORTED_PROPS = [
|
|
58
|
+
"fullWidth", // Recursica Button width comes from layout/token constraints, not Mantine's boolean fullWidth toggle.
|
|
59
|
+
] as const satisfies readonly (keyof MantineButtonProps)[];
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
62
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
63
|
+
UNSUPPORTED_PROPS,
|
|
64
|
+
) as Partial<typeof rest>;
|
|
65
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
57
66
|
|
|
58
67
|
const hasLeftSection = !!icon || !!restRecord["leftSection"];
|
|
59
68
|
const hasRightSection = !!restRecord["rightSection"];
|
|
@@ -78,41 +87,33 @@ const _Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
|
|
|
78
87
|
);
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
const mergedClassNames
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
classNamesProp &&
|
|
91
|
-
typeof classNamesProp === "object" &&
|
|
92
|
-
!Array.isArray(classNamesProp)
|
|
93
|
-
) {
|
|
94
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
95
|
-
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
96
|
-
mergedClassNames.section = o.section ?? styles.section;
|
|
97
|
-
mergedClassNames.label = o.label ?? styles.label;
|
|
98
|
-
}
|
|
90
|
+
const mergedClassNames = mergeClassNames(
|
|
91
|
+
{
|
|
92
|
+
root: styles.root,
|
|
93
|
+
section: styles.section,
|
|
94
|
+
label: styles.label,
|
|
95
|
+
loader: styles.loader,
|
|
96
|
+
},
|
|
97
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
98
|
+
);
|
|
99
99
|
|
|
100
100
|
const classNameProp = restRecord.className as string | undefined;
|
|
101
101
|
const finalClass = classNameProp
|
|
102
102
|
? `${styles.root} ${classNameProp}`
|
|
103
103
|
: styles.root;
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
delete restRecord["className"];
|
|
104
|
+
// Note: `finalClass` is safe from being clobbered by `{...sanitizedProps}` below purely
|
|
105
|
+
// because of spread order — `className` (like `classNames`, `variant`, `size`, `leftSection`,
|
|
106
|
+
// and the `data-*` attributes) is spread first, then re-asserted after, so our computed value
|
|
107
|
+
// always wins. See the canonical guide's §3.3 for why ordering (not deletion) is the fix here.
|
|
109
108
|
|
|
110
109
|
const userLoaderProps = restRecord.loaderProps as
|
|
111
110
|
| Record<string, unknown>
|
|
112
111
|
| undefined;
|
|
113
112
|
|
|
114
|
-
const resolvedLoaderSize =
|
|
115
|
-
|
|
113
|
+
const resolvedLoaderSize = withCallerOverride(
|
|
114
|
+
size === "small" ? "small" : "default",
|
|
115
|
+
loaderSize,
|
|
116
|
+
);
|
|
116
117
|
|
|
117
118
|
let mergedLoaderProps = userLoaderProps;
|
|
118
119
|
if (useRecursicaLoader) {
|
|
@@ -125,6 +126,7 @@ const _Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
|
|
|
125
126
|
return (
|
|
126
127
|
<MantineButton
|
|
127
128
|
ref={ref}
|
|
129
|
+
{...sanitizedProps}
|
|
128
130
|
className={finalClass}
|
|
129
131
|
classNames={mergedClassNames}
|
|
130
132
|
variant={mapVariant[variant]}
|
|
@@ -140,7 +142,6 @@ const _Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button(
|
|
|
140
142
|
data-variant={variant}
|
|
141
143
|
data-size={size}
|
|
142
144
|
data-content={contentType}
|
|
143
|
-
{...sanitizedProps}
|
|
144
145
|
disabled={!!restRecord.disabled || !!restRecord.loading}
|
|
145
146
|
>
|
|
146
147
|
<span className={styles.labelText}>{children}</span>
|