@recursica/mantine-adapter 0.42.1 → 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 +11 -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.js +3547 -3292
- package/dist/mantine-adapter.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.tsx +32 -33
- package/src/components/AssistiveElement/AssistiveElement.tsx +1 -1
- package/src/components/AutoComplete/AutoComplete.tsx +26 -38
- 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.tsx +34 -27
- package/src/components/DatePicker/DatePicker.tsx +46 -47
- package/src/components/Dropdown/BareDropdown.tsx +25 -13
- package/src/components/Dropdown/Dropdown.tsx +25 -38
- package/src/components/FileInput/FileInput.tsx +1 -1
- package/src/components/FileUpload/FileUpload.tsx +1 -1
- package/src/components/HoverCard/HoverCard.tsx +18 -34
- package/src/components/Label/Label.tsx +20 -21
- package/src/components/Link/Link.tsx +6 -14
- package/src/components/Loader/Loader.tsx +8 -16
- package/src/components/Menu/Menu.tsx +55 -48
- package/src/components/Modal/Modal.tsx +134 -96
- package/src/components/NumberInput/NumberInput.tsx +14 -7
- 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.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.tsx +21 -25
- package/src/components/TextField/TextField.tsx +23 -30
- package/src/components/TimePicker/TimePicker.tsx +26 -12
- 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.tsx +32 -31
- package/src/components/Tooltip/Tooltip.tsx +18 -34
- package/src/components/TransferList/TransferList.tsx +1 -1
- package/src/components/Tree/Tree.tsx +8 -8
- package/src/utils/filterStylingProps.ts +4 -0
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
7
7
|
import {
|
|
8
8
|
filterStylingProps,
|
|
9
|
+
omitUnsupportedProps,
|
|
10
|
+
mergeClassNames,
|
|
9
11
|
type RecursicaOverStyled,
|
|
10
12
|
} from "../../utils/filterStylingProps";
|
|
11
13
|
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
@@ -28,6 +30,14 @@ export interface RecursicaTextAreaProps
|
|
|
28
30
|
|
|
29
31
|
export type TextAreaProps = RecursicaOverStyled<RecursicaTextAreaProps>;
|
|
30
32
|
|
|
33
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
34
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
35
|
+
const UNSUPPORTED_PROPS = [
|
|
36
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
37
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
38
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
39
|
+
] as const satisfies readonly (keyof MantineTextareaProps)[];
|
|
40
|
+
|
|
31
41
|
export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
|
|
32
42
|
function TextArea(props, ref) {
|
|
33
43
|
const {
|
|
@@ -58,34 +68,20 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
|
|
|
58
68
|
defaultValue,
|
|
59
69
|
...rest
|
|
60
70
|
} = props;
|
|
61
|
-
const sanitizedProps =
|
|
71
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
72
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
73
|
+
UNSUPPORTED_PROPS,
|
|
74
|
+
);
|
|
62
75
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
63
76
|
|
|
64
|
-
// Delete prohibited sizing hooks from bypassing variables natively
|
|
65
|
-
delete restRecord["size"];
|
|
66
|
-
delete restRecord["variant"];
|
|
67
|
-
delete restRecord["radius"];
|
|
68
|
-
|
|
69
77
|
// Securely map core native blocks down ensuring nested CSS modules map precisely
|
|
70
|
-
const mergedClassNames
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
classNamesProp &&
|
|
78
|
-
typeof classNamesProp === "object" &&
|
|
79
|
-
!Array.isArray(classNamesProp)
|
|
80
|
-
) {
|
|
81
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
82
|
-
mergedClassNames.wrapper = o.wrapper
|
|
83
|
-
? `${styles.root} ${o.wrapper}`
|
|
84
|
-
: styles.root;
|
|
85
|
-
mergedClassNames.input = o.input
|
|
86
|
-
? `${styles.input} ${o.input}`
|
|
87
|
-
: styles.input;
|
|
88
|
-
}
|
|
78
|
+
const mergedClassNames = mergeClassNames(
|
|
79
|
+
{
|
|
80
|
+
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
81
|
+
input: styles.input,
|
|
82
|
+
},
|
|
83
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
84
|
+
);
|
|
89
85
|
|
|
90
86
|
const wrapperClass = className
|
|
91
87
|
? `${styles.layoutOverride} ${className}`
|
|
@@ -3,6 +3,8 @@ import { Input, type InputProps, type InputWrapperProps } from "@mantine/core";
|
|
|
3
3
|
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
4
4
|
import {
|
|
5
5
|
filterStylingProps,
|
|
6
|
+
omitUnsupportedProps,
|
|
7
|
+
mergeClassNames,
|
|
6
8
|
type RecursicaOverStyled,
|
|
7
9
|
} from "../../utils/filterStylingProps";
|
|
8
10
|
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
@@ -30,6 +32,14 @@ export interface RecursicaTextFieldProps
|
|
|
30
32
|
|
|
31
33
|
export type TextFieldProps = RecursicaOverStyled<RecursicaTextFieldProps>;
|
|
32
34
|
|
|
35
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
36
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
37
|
+
const UNSUPPORTED_PROPS = [
|
|
38
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
39
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
40
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
41
|
+
] as const satisfies readonly (keyof InputProps)[];
|
|
42
|
+
|
|
33
43
|
export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
34
44
|
function TextField(props, ref) {
|
|
35
45
|
const {
|
|
@@ -60,38 +70,21 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
60
70
|
defaultValue,
|
|
61
71
|
...rest
|
|
62
72
|
} = props;
|
|
63
|
-
const sanitizedProps =
|
|
73
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
74
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
75
|
+
UNSUPPORTED_PROPS,
|
|
76
|
+
);
|
|
64
77
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
65
78
|
|
|
66
|
-
// Delete prohibited sizing hooks from bypassing variables natively
|
|
67
|
-
delete restRecord["size"];
|
|
68
|
-
delete restRecord["variant"];
|
|
69
|
-
delete restRecord["radius"];
|
|
70
|
-
|
|
71
79
|
// Securely map core native blocks down ensuring nested CSS modules map precisely
|
|
72
|
-
const mergedClassNames
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
classNamesProp &&
|
|
81
|
-
typeof classNamesProp === "object" &&
|
|
82
|
-
!Array.isArray(classNamesProp)
|
|
83
|
-
) {
|
|
84
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
85
|
-
mergedClassNames.wrapper = o.wrapper
|
|
86
|
-
? `${styles.root} ${o.wrapper}`
|
|
87
|
-
: styles.root;
|
|
88
|
-
mergedClassNames.input = o.input
|
|
89
|
-
? `${styles.input} ${o.input}`
|
|
90
|
-
: styles.input;
|
|
91
|
-
mergedClassNames.section = o.section
|
|
92
|
-
? `${styles.section} ${o.section}`
|
|
93
|
-
: styles.section;
|
|
94
|
-
}
|
|
80
|
+
const mergedClassNames = mergeClassNames(
|
|
81
|
+
{
|
|
82
|
+
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
83
|
+
input: styles.input,
|
|
84
|
+
section: styles.section,
|
|
85
|
+
},
|
|
86
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
87
|
+
);
|
|
95
88
|
|
|
96
89
|
const wrapperClass = className
|
|
97
90
|
? `${styles.layoutOverride} ${className}`
|
|
@@ -127,6 +120,7 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
127
120
|
/* Naked Input execution safely decoupled from Mantine's macro Input.Wrapper DOM hooks */
|
|
128
121
|
<Input
|
|
129
122
|
ref={ref}
|
|
123
|
+
{...(sanitizedProps as unknown as InputProps)}
|
|
130
124
|
classNames={mergedClassNames}
|
|
131
125
|
disabled={disabled}
|
|
132
126
|
value={value}
|
|
@@ -135,7 +129,6 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
|
|
|
135
129
|
"data-disabled": disabled ? "true" : undefined,
|
|
136
130
|
"data-error": error ? "true" : undefined,
|
|
137
131
|
}}
|
|
138
|
-
{...(sanitizedProps as unknown as InputProps)}
|
|
139
132
|
/>
|
|
140
133
|
}
|
|
141
134
|
/>
|
|
@@ -7,6 +7,8 @@ import { type InputWrapperProps } from "@mantine/core";
|
|
|
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";
|
|
@@ -102,6 +104,14 @@ export interface RecursicaTimePickerProps
|
|
|
102
104
|
|
|
103
105
|
export type TimePickerProps = RecursicaOverStyled<RecursicaTimePickerProps>;
|
|
104
106
|
|
|
107
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
108
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
109
|
+
const UNSUPPORTED_PROPS = [
|
|
110
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
111
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
112
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
113
|
+
] as const satisfies readonly (keyof MantineTimePickerProps)[];
|
|
114
|
+
|
|
105
115
|
export const TimePicker = forwardRef<HTMLDivElement, TimePickerProps>(
|
|
106
116
|
function TimePicker(props, ref) {
|
|
107
117
|
const {
|
|
@@ -137,13 +147,12 @@ export const TimePicker = forwardRef<HTMLDivElement, TimePickerProps>(
|
|
|
137
147
|
...rest
|
|
138
148
|
} = props;
|
|
139
149
|
|
|
140
|
-
const sanitizedProps =
|
|
150
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
151
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
152
|
+
UNSUPPORTED_PROPS,
|
|
153
|
+
);
|
|
141
154
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
142
155
|
|
|
143
|
-
delete restRecord["size"];
|
|
144
|
-
delete restRecord["variant"];
|
|
145
|
-
delete restRecord["radius"];
|
|
146
|
-
|
|
147
156
|
// Internal full 24-hour value. Needed because Mantine's TimePicker (hour/minute/second entry)
|
|
148
157
|
// and our own BareDropdown (AM/PM) both mutate the same conceptual value — see
|
|
149
158
|
// TIMEPICKER_IMPLEMENTATION_NOTES.md.
|
|
@@ -241,12 +250,18 @@ export const TimePicker = forwardRef<HTMLDivElement, TimePickerProps>(
|
|
|
241
250
|
>
|
|
242
251
|
<MantineTimePicker
|
|
243
252
|
ref={ref}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
253
|
+
{...(sanitizedProps as unknown as MantineTimePickerProps)}
|
|
254
|
+
classNames={mergeClassNames(
|
|
255
|
+
{
|
|
256
|
+
wrapper: styles.timeWrapper,
|
|
257
|
+
input: styles.timeInput,
|
|
258
|
+
fieldsGroup: styles.fieldsGroup,
|
|
259
|
+
field: styles.timeField,
|
|
260
|
+
},
|
|
261
|
+
restRecord.classNames as
|
|
262
|
+
| Partial<Record<string, string>>
|
|
263
|
+
| undefined,
|
|
264
|
+
)}
|
|
250
265
|
disabled={disabled}
|
|
251
266
|
value={internalValue}
|
|
252
267
|
onChange={handleFieldChange}
|
|
@@ -259,7 +274,6 @@ export const TimePicker = forwardRef<HTMLDivElement, TimePickerProps>(
|
|
|
259
274
|
// to seed the mount-time AM default onto Mantine's own hidden native select. See
|
|
260
275
|
// TIMEPICKER_IMPLEMENTATION_NOTES.md.
|
|
261
276
|
amPmRef={amPmRef}
|
|
262
|
-
{...(sanitizedProps as unknown as MantineTimePickerProps)}
|
|
263
277
|
/>
|
|
264
278
|
<BareDropdown
|
|
265
279
|
overStyled
|
|
@@ -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 "./Timeline.module.css";
|
|
@@ -46,36 +47,21 @@ interface TimelineComponent
|
|
|
46
47
|
const TimelineInner = React.forwardRef<HTMLDivElement, TimelineProps>(
|
|
47
48
|
function Timeline({ overStyled = false, ...rest }, ref) {
|
|
48
49
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
50
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
49
51
|
|
|
50
|
-
const mergedClassNames
|
|
51
|
-
root: styles.root,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const classNamesProp = (sanitizedProps as Record<string, unknown>)
|
|
55
|
-
.classNames;
|
|
56
|
-
if (
|
|
57
|
-
classNamesProp &&
|
|
58
|
-
typeof classNamesProp === "object" &&
|
|
59
|
-
!Array.isArray(classNamesProp)
|
|
60
|
-
) {
|
|
61
|
-
const o = classNamesProp as Record<string, string>;
|
|
62
|
-
Object.keys(o).forEach((key) => {
|
|
63
|
-
if (mergedClassNames[key]) {
|
|
64
|
-
mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
|
|
65
|
-
} else {
|
|
66
|
-
mergedClassNames[key] = o[key];
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
}
|
|
52
|
+
const mergedClassNames = mergeClassNames(
|
|
53
|
+
{ root: styles.root },
|
|
54
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
55
|
+
);
|
|
70
56
|
|
|
71
57
|
return (
|
|
72
58
|
<MantineTimeline
|
|
73
59
|
ref={ref}
|
|
74
|
-
classNames={mergedClassNames}
|
|
75
60
|
{...(sanitizedProps as unknown as Omit<
|
|
76
61
|
MantineTimelineProps,
|
|
77
62
|
"color" | "radius" | "bulletSize" | "lineWidth"
|
|
78
63
|
>)}
|
|
64
|
+
classNames={mergedClassNames}
|
|
79
65
|
/>
|
|
80
66
|
);
|
|
81
67
|
},
|
|
@@ -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 "./Timeline.module.css";
|
|
@@ -36,31 +37,18 @@ export const TimelineItem = React.forwardRef<HTMLDivElement, TimelineItemProps>(
|
|
|
36
37
|
ref,
|
|
37
38
|
) {
|
|
38
39
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
40
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
39
41
|
|
|
40
|
-
const mergedClassNames
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
classNamesProp &&
|
|
52
|
-
typeof classNamesProp === "object" &&
|
|
53
|
-
!Array.isArray(classNamesProp)
|
|
54
|
-
) {
|
|
55
|
-
const o = classNamesProp as Record<string, string>;
|
|
56
|
-
Object.keys(o).forEach((key) => {
|
|
57
|
-
if (mergedClassNames[key]) {
|
|
58
|
-
mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
|
|
59
|
-
} else {
|
|
60
|
-
mergedClassNames[key] = o[key];
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
}
|
|
42
|
+
const mergedClassNames = mergeClassNames(
|
|
43
|
+
{
|
|
44
|
+
item: styles.item,
|
|
45
|
+
itemBody: styles.itemBody,
|
|
46
|
+
itemContent: styles.itemContent,
|
|
47
|
+
itemBullet: styles.itemBullet,
|
|
48
|
+
itemTitle: styles.itemTitle,
|
|
49
|
+
},
|
|
50
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
51
|
+
);
|
|
64
52
|
|
|
65
53
|
// Embed timestamp inside children if provided, wrapped in a specific class
|
|
66
54
|
const content = timestamp ? (
|
|
@@ -75,12 +63,12 @@ export const TimelineItem = React.forwardRef<HTMLDivElement, TimelineItemProps>(
|
|
|
75
63
|
return (
|
|
76
64
|
<MantineTimelineItem
|
|
77
65
|
ref={ref}
|
|
78
|
-
classNames={mergedClassNames}
|
|
79
|
-
data-variant={bulletVariant}
|
|
80
66
|
{...(sanitizedProps as unknown as Omit<
|
|
81
67
|
MantineTimelineItemProps,
|
|
82
68
|
"radius" | "color" | "lineVariant"
|
|
83
69
|
>)}
|
|
70
|
+
classNames={mergedClassNames}
|
|
71
|
+
data-variant={bulletVariant}
|
|
84
72
|
>
|
|
85
73
|
{content}
|
|
86
74
|
</MantineTimelineItem>
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from "@mantine/core";
|
|
6
6
|
import {
|
|
7
7
|
filterStylingProps,
|
|
8
|
+
omitUnsupportedProps,
|
|
8
9
|
type RecursicaOverStyled,
|
|
9
10
|
} from "../../utils/filterStylingProps";
|
|
10
11
|
|
|
@@ -21,7 +22,16 @@ export const Title = forwardRef<HTMLHeadingElement, TitleProps>(function Title(
|
|
|
21
22
|
{ overStyled = false, order = 1, ...rest },
|
|
22
23
|
ref,
|
|
23
24
|
) {
|
|
24
|
-
|
|
25
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
26
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
27
|
+
const UNSUPPORTED_PROPS = [
|
|
28
|
+
"size", // Recursica controls Title sizing via the `order` prop + typography tokens, not Mantine's native `size`.
|
|
29
|
+
] as const satisfies readonly (keyof MantineTitleProps)[];
|
|
30
|
+
|
|
31
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
32
|
+
filterStylingProps(rest, overStyled),
|
|
33
|
+
UNSUPPORTED_PROPS,
|
|
34
|
+
);
|
|
25
35
|
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
26
36
|
.className as string | undefined;
|
|
27
37
|
|
|
@@ -33,9 +43,9 @@ export const Title = forwardRef<HTMLHeadingElement, TitleProps>(function Title(
|
|
|
33
43
|
return (
|
|
34
44
|
<MantineTitle
|
|
35
45
|
ref={ref}
|
|
46
|
+
{...(sanitizedProps as unknown as MantineTitleProps)}
|
|
36
47
|
order={order}
|
|
37
48
|
className={mergedClassName}
|
|
38
|
-
{...(sanitizedProps as unknown as MantineTitleProps)}
|
|
39
49
|
/>
|
|
40
50
|
);
|
|
41
51
|
});
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
} from "@mantine/core";
|
|
6
6
|
import {
|
|
7
7
|
filterStylingProps,
|
|
8
|
+
omitUnsupportedProps,
|
|
9
|
+
mergeClassNames,
|
|
8
10
|
type RecursicaOverStyled,
|
|
9
11
|
} from "../../utils/filterStylingProps";
|
|
10
12
|
import styles from "./Toast.module.css";
|
|
@@ -31,48 +33,47 @@ export const Toast = React.forwardRef<HTMLDivElement, ToastProps>(
|
|
|
31
33
|
},
|
|
32
34
|
ref,
|
|
33
35
|
) {
|
|
34
|
-
|
|
36
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
37
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
38
|
+
const UNSUPPORTED_PROPS = [
|
|
39
|
+
"color", // Colors are token-driven via `data-variant`; Mantine's native palette isn't exposed.
|
|
40
|
+
"radius", // Toast corner radius is controlled by design tokens, not a raw radius prop.
|
|
41
|
+
"loading", // Toast never renders a loading state; always forced off via `loading={false}` below.
|
|
42
|
+
] as const satisfies readonly (keyof MantineNotificationProps)[];
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
title: styles.title,
|
|
41
|
-
description: styles.description,
|
|
42
|
-
closeButton: styles.closeButton,
|
|
43
|
-
icon: styles.icon,
|
|
44
|
-
loader: styles.loader,
|
|
45
|
-
};
|
|
44
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
45
|
+
filterStylingProps(rest, overStyled),
|
|
46
|
+
UNSUPPORTED_PROPS,
|
|
47
|
+
);
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
49
|
+
// Bind CSS module classes to Mantine's internal classNames API
|
|
50
|
+
const mergedClassNames = mergeClassNames(
|
|
51
|
+
{
|
|
52
|
+
root: styles.root,
|
|
53
|
+
body: styles.body,
|
|
54
|
+
title: styles.title,
|
|
55
|
+
description: styles.description,
|
|
56
|
+
closeButton: styles.closeButton,
|
|
57
|
+
icon: styles.icon,
|
|
58
|
+
loader: styles.loader,
|
|
59
|
+
},
|
|
60
|
+
(sanitizedProps as Record<string, unknown>).classNames as
|
|
61
|
+
| Partial<Record<string, string>>
|
|
62
|
+
| undefined,
|
|
63
|
+
);
|
|
63
64
|
|
|
64
65
|
return (
|
|
65
66
|
<MantineNotification
|
|
66
67
|
ref={ref}
|
|
68
|
+
{...(sanitizedProps as unknown as Omit<
|
|
69
|
+
MantineNotificationProps,
|
|
70
|
+
"color" | "radius" | "variant" | "loading"
|
|
71
|
+
>)}
|
|
67
72
|
withCloseButton={withCloseButton}
|
|
68
73
|
withBorder={false} // Border is handled via CSS or tokens if needed
|
|
69
74
|
data-variant={variant}
|
|
70
75
|
classNames={mergedClassNames}
|
|
71
76
|
loading={false}
|
|
72
|
-
{...(sanitizedProps as unknown as Omit<
|
|
73
|
-
MantineNotificationProps,
|
|
74
|
-
"color" | "radius" | "variant" | "loading"
|
|
75
|
-
>)}
|
|
76
77
|
/>
|
|
77
78
|
);
|
|
78
79
|
},
|
|
@@ -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 "./Tooltip.module.css";
|
|
@@ -43,55 +44,38 @@ export type TooltipProps = RecursicaOverStyled<
|
|
|
43
44
|
const TooltipBase = function Tooltip({
|
|
44
45
|
overStyled = false,
|
|
45
46
|
withBeak = true,
|
|
47
|
+
position = "top", // Recursica default; Mantine defaults to "bottom"
|
|
48
|
+
// arrowSize must be a JS number prop — Mantine uses it for inline width/height
|
|
49
|
+
// and positioning offset (-arrowSize/2) calculations that cannot be CSS-driven.
|
|
50
|
+
// Default to 16 to match the Recursica beak-size token (16px).
|
|
51
|
+
arrowSize = 16,
|
|
46
52
|
...rest
|
|
47
53
|
}: TooltipProps) {
|
|
48
54
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
55
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
49
56
|
|
|
50
57
|
// Bind CSS module classes to Mantine's internal classNames API
|
|
51
|
-
const mergedClassNames
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
classNamesProp &&
|
|
59
|
-
typeof classNamesProp === "object" &&
|
|
60
|
-
!Array.isArray(classNamesProp)
|
|
61
|
-
) {
|
|
62
|
-
const o = classNamesProp as Record<string, string>;
|
|
63
|
-
Object.keys(o).forEach((key) => {
|
|
64
|
-
if (mergedClassNames[key]) {
|
|
65
|
-
mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
|
|
66
|
-
} else {
|
|
67
|
-
mergedClassNames[key] = o[key];
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// arrowSize must be a JS number prop — Mantine uses it for inline width/height
|
|
73
|
-
// and positioning offset (-arrowSize/2) calculations that cannot be CSS-driven.
|
|
74
|
-
// Default to 16 to match the Recursica beak-size token (16px).
|
|
75
|
-
const arrowSize =
|
|
76
|
-
((sanitizedProps as Record<string, unknown>).arrowSize as
|
|
77
|
-
| number
|
|
78
|
-
| undefined) ?? 16;
|
|
58
|
+
const mergedClassNames = mergeClassNames(
|
|
59
|
+
{
|
|
60
|
+
tooltip: styles.tooltip,
|
|
61
|
+
arrow: styles.arrow,
|
|
62
|
+
},
|
|
63
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
64
|
+
);
|
|
79
65
|
|
|
80
66
|
// Resolve withBeak (Recursica) vs withArrow (Mantine).
|
|
81
67
|
// withBeak takes precedence when both are provided.
|
|
82
|
-
const withArrow =
|
|
83
|
-
| boolean
|
|
84
|
-
| undefined;
|
|
68
|
+
const withArrow = restRecord.withArrow as boolean | undefined;
|
|
85
69
|
const resolvedWithArrow = withBeak ?? withArrow;
|
|
86
70
|
|
|
87
71
|
return (
|
|
88
72
|
<MantineTooltip
|
|
89
|
-
|
|
90
|
-
|
|
73
|
+
{...(sanitizedProps as unknown as MantineTooltipProps)}
|
|
74
|
+
position={position}
|
|
91
75
|
arrowSize={arrowSize}
|
|
92
76
|
withArrow={resolvedWithArrow}
|
|
77
|
+
multiline /* Always allow text wrapping within max-width */
|
|
93
78
|
classNames={mergedClassNames}
|
|
94
|
-
{...(sanitizedProps as unknown as MantineTooltipProps)}
|
|
95
79
|
/>
|
|
96
80
|
);
|
|
97
81
|
};
|
|
@@ -346,10 +346,10 @@ export const TransferList = forwardRef<HTMLDivElement, TransferListProps>(
|
|
|
346
346
|
readOnlyNativeProps={props}
|
|
347
347
|
activeComponent={
|
|
348
348
|
<div
|
|
349
|
+
{...(sanitizedProps as Record<string, unknown>)}
|
|
349
350
|
className={styles.root}
|
|
350
351
|
data-disabled={disabled ? "true" : undefined}
|
|
351
352
|
data-error={error ? "true" : undefined}
|
|
352
|
-
{...(sanitizedProps as Record<string, unknown>)}
|
|
353
353
|
>
|
|
354
354
|
<div className={styles.panes}>
|
|
355
355
|
{renderPane(
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { useMergedRef } from "@mantine/hooks";
|
|
9
9
|
import {
|
|
10
10
|
filterStylingProps,
|
|
11
|
+
mergeClassNames,
|
|
11
12
|
type RecursicaOverStyled,
|
|
12
13
|
} from "../../utils/filterStylingProps";
|
|
13
14
|
import { type RecursicaTreeProps } from "@recursica/adapter-common";
|
|
@@ -186,8 +187,8 @@ export const Tree = forwardRef<HTMLUListElement, TreeProps>(function Tree(
|
|
|
186
187
|
}, [disabled]);
|
|
187
188
|
const mergedRef = useMergedRef(ref, rootRef);
|
|
188
189
|
|
|
189
|
-
const
|
|
190
|
-
|
|
190
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
191
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
191
192
|
const rootClass = classNameProp
|
|
192
193
|
? `${styles.root} ${classNameProp}`
|
|
193
194
|
: styles.root;
|
|
@@ -195,6 +196,7 @@ export const Tree = forwardRef<HTMLUListElement, TreeProps>(function Tree(
|
|
|
195
196
|
return (
|
|
196
197
|
<MantineTree
|
|
197
198
|
ref={mergedRef}
|
|
199
|
+
{...(sanitizedProps as unknown as Record<string, unknown>)}
|
|
198
200
|
data={data}
|
|
199
201
|
tree={tree}
|
|
200
202
|
expandOnClick={false}
|
|
@@ -202,12 +204,10 @@ export const Tree = forwardRef<HTMLUListElement, TreeProps>(function Tree(
|
|
|
202
204
|
expandOnSpace={false}
|
|
203
205
|
renderNode={createRenderTreeNode(disabled)}
|
|
204
206
|
data-disabled={disabled || undefined}
|
|
205
|
-
classNames={
|
|
206
|
-
root: rootClass,
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}}
|
|
210
|
-
{...(sanitizedProps as unknown as Record<string, unknown>)}
|
|
207
|
+
classNames={mergeClassNames(
|
|
208
|
+
{ root: rootClass, node: styles.node, subtree: styles.subtree },
|
|
209
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
210
|
+
)}
|
|
211
211
|
/>
|
|
212
212
|
);
|
|
213
213
|
});
|