@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
|
@@ -8,9 +8,12 @@ import {
|
|
|
8
8
|
type ModalHeaderProps as MantineModalHeaderProps,
|
|
9
9
|
type ModalTitleProps as MantineModalTitleProps,
|
|
10
10
|
type ModalCloseButtonProps as MantineModalCloseButtonProps,
|
|
11
|
+
type ModalBodyProps as MantineModalBodyProps,
|
|
11
12
|
} from "@mantine/core";
|
|
12
13
|
import {
|
|
13
14
|
filterStylingProps,
|
|
15
|
+
omitUnsupportedProps,
|
|
16
|
+
mergeClassNames,
|
|
14
17
|
type RecursicaOverStyled,
|
|
15
18
|
} from "../../utils/filterStylingProps";
|
|
16
19
|
import styles from "./Modal.module.css";
|
|
@@ -54,41 +57,40 @@ const ModalInner = React.forwardRef<HTMLDivElement, ModalProps>(function Modal(
|
|
|
54
57
|
},
|
|
55
58
|
ref,
|
|
56
59
|
) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
60
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
61
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
62
|
+
const UNSUPPORTED_PROPS = [
|
|
63
|
+
"size", // Modal width/height are enforced via CSS module tokens (min/max-width, min/max-height), not Mantine's `size` scale.
|
|
64
|
+
"radius", // Modal corner radius is token-driven via `.content` in Modal.module.css, not Mantine's `radius` prop.
|
|
65
|
+
] as const satisfies readonly (keyof MantineModalProps)[];
|
|
66
|
+
|
|
67
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
68
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
69
|
+
UNSUPPORTED_PROPS,
|
|
70
|
+
) as Partial<typeof rest>;
|
|
71
|
+
|
|
72
|
+
const mergedClassNames = mergeClassNames(
|
|
73
|
+
{
|
|
74
|
+
root: styles.root,
|
|
75
|
+
inner: styles.inner,
|
|
76
|
+
content: styles.content,
|
|
77
|
+
header: styles.header,
|
|
78
|
+
title: styles.title,
|
|
79
|
+
close: styles.close,
|
|
80
|
+
},
|
|
81
|
+
(sanitizedProps as Record<string, unknown>).classNames as
|
|
82
|
+
| Partial<Record<string, string>>
|
|
83
|
+
| undefined,
|
|
84
|
+
);
|
|
83
85
|
|
|
84
86
|
return (
|
|
85
87
|
<MantineModal.Root
|
|
86
88
|
ref={ref}
|
|
87
|
-
classNames={mergedClassNames}
|
|
88
89
|
{...(sanitizedProps as unknown as Omit<
|
|
89
90
|
MantineModalProps,
|
|
90
91
|
"size" | "radius" | "shadow"
|
|
91
92
|
>)}
|
|
93
|
+
classNames={mergedClassNames}
|
|
92
94
|
>
|
|
93
95
|
{withOverlay && <MantineModal.Overlay {...overlayProps} />}
|
|
94
96
|
<MantineModal.Content>
|
|
@@ -130,81 +132,87 @@ const ModalFooter = React.forwardRef<HTMLDivElement, ModalFooterProps>(
|
|
|
130
132
|
return (
|
|
131
133
|
<div
|
|
132
134
|
ref={ref}
|
|
133
|
-
className={`${styles.footer} ${className || ""}`}
|
|
134
135
|
{...sanitizedProps}
|
|
136
|
+
className={`${styles.footer} ${className || ""}`}
|
|
135
137
|
/>
|
|
136
138
|
);
|
|
137
139
|
},
|
|
138
140
|
);
|
|
139
141
|
ModalFooter.displayName = "Modal.Footer";
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
HTMLDivElement,
|
|
143
|
-
React.ComponentPropsWithoutRef<typeof MantineModal.Body>
|
|
144
|
-
>(function ModalBody({ className, onScroll, children, ...rest }, ref) {
|
|
145
|
-
const internalRef = React.useRef<HTMLDivElement>(null);
|
|
146
|
-
const [scrolledTop, setScrolledTop] = React.useState(false);
|
|
147
|
-
const [scrolledBottom, setScrolledBottom] = React.useState(false);
|
|
148
|
-
|
|
149
|
-
const checkScroll = React.useCallback(() => {
|
|
150
|
-
if (internalRef.current) {
|
|
151
|
-
const { scrollTop, scrollHeight, clientHeight } = internalRef.current;
|
|
152
|
-
setScrolledTop(scrollTop > 0);
|
|
153
|
-
setScrolledBottom(Math.ceil(scrollTop + clientHeight) < scrollHeight);
|
|
154
|
-
}
|
|
155
|
-
}, []);
|
|
156
|
-
|
|
157
|
-
// Re-check scroll on mount and window resize
|
|
158
|
-
React.useEffect(() => {
|
|
159
|
-
checkScroll();
|
|
160
|
-
window.addEventListener("resize", checkScroll);
|
|
161
|
-
return () => window.removeEventListener("resize", checkScroll);
|
|
162
|
-
}, [checkScroll, children]);
|
|
163
|
-
|
|
164
|
-
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
|
|
165
|
-
checkScroll();
|
|
166
|
-
onScroll?.(e);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// Intercept children to pull Modal.Footer out of the scrolling container
|
|
170
|
-
let footer: React.ReactNode = null;
|
|
171
|
-
const bodyChildren: React.ReactNode[] = [];
|
|
172
|
-
|
|
173
|
-
React.Children.forEach(children, (child) => {
|
|
174
|
-
if (
|
|
175
|
-
React.isValidElement(child) &&
|
|
176
|
-
(child.type === ModalFooter ||
|
|
177
|
-
(child.type as React.ComponentType)?.displayName === "Modal.Footer")
|
|
178
|
-
) {
|
|
179
|
-
footer = child;
|
|
180
|
-
} else {
|
|
181
|
-
bodyChildren.push(child);
|
|
182
|
-
}
|
|
183
|
-
});
|
|
143
|
+
export type ModalBodyProps = RecursicaOverStyled<MantineModalBodyProps>;
|
|
184
144
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
145
|
+
const ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(
|
|
146
|
+
function ModalBody(
|
|
147
|
+
{ overStyled = false, className, onScroll, children, ...rest },
|
|
148
|
+
ref,
|
|
149
|
+
) {
|
|
150
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
151
|
+
const internalRef = React.useRef<HTMLDivElement>(null);
|
|
152
|
+
const [scrolledTop, setScrolledTop] = React.useState(false);
|
|
153
|
+
const [scrolledBottom, setScrolledBottom] = React.useState(false);
|
|
154
|
+
|
|
155
|
+
const checkScroll = React.useCallback(() => {
|
|
156
|
+
if (internalRef.current) {
|
|
157
|
+
const { scrollTop, scrollHeight, clientHeight } = internalRef.current;
|
|
158
|
+
setScrolledTop(scrollTop > 0);
|
|
159
|
+
setScrolledBottom(Math.ceil(scrollTop + clientHeight) < scrollHeight);
|
|
160
|
+
}
|
|
161
|
+
}, []);
|
|
162
|
+
|
|
163
|
+
// Re-check scroll on mount and window resize
|
|
164
|
+
React.useEffect(() => {
|
|
165
|
+
checkScroll();
|
|
166
|
+
window.addEventListener("resize", checkScroll);
|
|
167
|
+
return () => window.removeEventListener("resize", checkScroll);
|
|
168
|
+
}, [checkScroll, children]);
|
|
169
|
+
|
|
170
|
+
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
|
|
171
|
+
checkScroll();
|
|
172
|
+
onScroll?.(e);
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// Intercept children to pull Modal.Footer out of the scrolling container
|
|
176
|
+
let footer: React.ReactNode = null;
|
|
177
|
+
const bodyChildren: React.ReactNode[] = [];
|
|
178
|
+
|
|
179
|
+
React.Children.forEach(children, (child) => {
|
|
180
|
+
if (
|
|
181
|
+
React.isValidElement(child) &&
|
|
182
|
+
(child.type === ModalFooter ||
|
|
183
|
+
(child.type as React.ComponentType)?.displayName === "Modal.Footer")
|
|
184
|
+
) {
|
|
185
|
+
footer = child;
|
|
186
|
+
} else {
|
|
187
|
+
bodyChildren.push(child);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<MantineModal.Body
|
|
193
|
+
{...sanitizedProps}
|
|
194
|
+
ref={(node) => {
|
|
195
|
+
if (typeof ref === "function") ref(node);
|
|
196
|
+
else if (ref)
|
|
197
|
+
(ref as React.MutableRefObject<HTMLDivElement | null>).current =
|
|
198
|
+
node;
|
|
199
|
+
}}
|
|
200
|
+
className={`${styles.bodyWrapper} ${className || ""}`}
|
|
201
201
|
>
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
202
|
+
<div
|
|
203
|
+
ref={internalRef}
|
|
204
|
+
onScroll={handleScroll}
|
|
205
|
+
data-scrolled-top={scrolledTop || undefined}
|
|
206
|
+
data-scrolled-bottom={scrolledBottom || undefined}
|
|
207
|
+
className={styles.scrollArea}
|
|
208
|
+
>
|
|
209
|
+
{bodyChildren}
|
|
210
|
+
</div>
|
|
211
|
+
{footer}
|
|
212
|
+
</MantineModal.Body>
|
|
213
|
+
);
|
|
214
|
+
},
|
|
215
|
+
);
|
|
208
216
|
ModalBody.displayName = "Modal.Body";
|
|
209
217
|
|
|
210
218
|
// ============================================================
|
|
@@ -213,9 +221,20 @@ ModalBody.displayName = "Modal.Body";
|
|
|
213
221
|
|
|
214
222
|
export type ModalRootProps = RecursicaOverStyled<MantineModalRootProps>;
|
|
215
223
|
|
|
224
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
225
|
+
// through even if a caller forces them via plain JavaScript. `Modal.Root` is used directly for
|
|
226
|
+
// advanced composition, so it doesn't benefit from the top-level `Modal`'s `Omit<>` protection.
|
|
227
|
+
const MODAL_ROOT_UNSUPPORTED_PROPS = [
|
|
228
|
+
"size", // Modal width/height are enforced via CSS module tokens, not Mantine's `size` scale.
|
|
229
|
+
"radius", // Modal corner radius is token-driven via `.content` in Modal.module.css, not Mantine's `radius` prop.
|
|
230
|
+
] as const satisfies readonly (keyof MantineModalRootProps)[];
|
|
231
|
+
|
|
216
232
|
const ModalRoot = React.forwardRef<HTMLDivElement, ModalRootProps>(
|
|
217
233
|
function ModalRoot({ overStyled = false, ...rest }, ref) {
|
|
218
|
-
const sanitizedProps =
|
|
234
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
235
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
236
|
+
MODAL_ROOT_UNSUPPORTED_PROPS,
|
|
237
|
+
) as Partial<typeof rest>;
|
|
219
238
|
return (
|
|
220
239
|
<MantineModal.Root
|
|
221
240
|
ref={ref}
|
|
@@ -243,9 +262,18 @@ ModalOverlay.displayName = "Modal.Overlay";
|
|
|
243
262
|
|
|
244
263
|
export type ModalContentProps = RecursicaOverStyled<MantineModalContentProps>;
|
|
245
264
|
|
|
265
|
+
// Modal corner radius is token-driven via `.content` in Modal.module.css, not Mantine's
|
|
266
|
+
// native `radius` prop — deleted at runtime so it can't leak through via plain JavaScript.
|
|
267
|
+
const MODAL_CONTENT_UNSUPPORTED_PROPS = [
|
|
268
|
+
"radius",
|
|
269
|
+
] as const satisfies readonly (keyof MantineModalContentProps)[];
|
|
270
|
+
|
|
246
271
|
const ModalContent = React.forwardRef<HTMLDivElement, ModalContentProps>(
|
|
247
272
|
function ModalContent({ overStyled = false, ...rest }, ref) {
|
|
248
|
-
const sanitizedProps =
|
|
273
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
274
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
275
|
+
MODAL_CONTENT_UNSUPPORTED_PROPS,
|
|
276
|
+
) as Partial<typeof rest>;
|
|
249
277
|
return (
|
|
250
278
|
<MantineModal.Content
|
|
251
279
|
ref={ref}
|
|
@@ -289,11 +317,21 @@ ModalTitle.displayName = "Modal.Title";
|
|
|
289
317
|
export type ModalCloseButtonProps =
|
|
290
318
|
RecursicaOverStyled<MantineModalCloseButtonProps>;
|
|
291
319
|
|
|
320
|
+
// The close button's dimensions and corner radius are enforced by Modal.module.css's `.close`
|
|
321
|
+
// (standard icon-button tokens), not Mantine's native `size`/`radius` scales.
|
|
322
|
+
const MODAL_CLOSE_BUTTON_UNSUPPORTED_PROPS = [
|
|
323
|
+
"size",
|
|
324
|
+
"radius",
|
|
325
|
+
] as const satisfies readonly (keyof MantineModalCloseButtonProps)[];
|
|
326
|
+
|
|
292
327
|
const ModalCloseButton = React.forwardRef<
|
|
293
328
|
HTMLButtonElement,
|
|
294
329
|
ModalCloseButtonProps
|
|
295
330
|
>(function ModalCloseButton({ overStyled = false, ...rest }, ref) {
|
|
296
|
-
const sanitizedProps =
|
|
331
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
332
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
333
|
+
MODAL_CLOSE_BUTTON_UNSUPPORTED_PROPS,
|
|
334
|
+
) as Partial<typeof rest>;
|
|
297
335
|
return (
|
|
298
336
|
<MantineModal.CloseButton
|
|
299
337
|
ref={ref}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
7
7
|
import {
|
|
8
8
|
filterStylingProps,
|
|
9
|
+
omitUnsupportedProps,
|
|
9
10
|
type RecursicaOverStyled,
|
|
10
11
|
} from "../../utils/filterStylingProps";
|
|
11
12
|
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
@@ -35,6 +36,14 @@ export interface RecursicaNumberInputProps
|
|
|
35
36
|
|
|
36
37
|
export type NumberInputProps = RecursicaOverStyled<RecursicaNumberInputProps>;
|
|
37
38
|
|
|
39
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
40
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
41
|
+
const UNSUPPORTED_PROPS = [
|
|
42
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
43
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
44
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
45
|
+
] as const satisfies readonly (keyof MantineNumberInputProps)[];
|
|
46
|
+
|
|
38
47
|
export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
|
|
39
48
|
function NumberInput(props, ref) {
|
|
40
49
|
const {
|
|
@@ -67,14 +76,12 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
|
|
|
67
76
|
...rest
|
|
68
77
|
} = props;
|
|
69
78
|
|
|
70
|
-
const sanitizedProps =
|
|
79
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
80
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
81
|
+
UNSUPPORTED_PROPS,
|
|
82
|
+
);
|
|
71
83
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
72
84
|
|
|
73
|
-
// Delete prohibited sizing hooks from bypassing variables natively
|
|
74
|
-
delete restRecord["size"];
|
|
75
|
-
delete restRecord["variant"];
|
|
76
|
-
delete restRecord["radius"];
|
|
77
|
-
|
|
78
85
|
// Securely map core native blocks down ensuring nested CSS modules map precisely
|
|
79
86
|
const mergedClassNames: Partial<Record<string, string>> = {
|
|
80
87
|
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
@@ -120,6 +127,7 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
|
|
|
120
127
|
/* Naked Input execution safely decoupled from Mantine's macro Input.Wrapper DOM hooks */
|
|
121
128
|
<MantineNumberInput
|
|
122
129
|
ref={ref}
|
|
130
|
+
{...(sanitizedProps as unknown as MantineNumberInputProps)}
|
|
123
131
|
classNames={mergedClassNames}
|
|
124
132
|
disabled={disabled}
|
|
125
133
|
value={value}
|
|
@@ -139,7 +147,6 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
|
|
|
139
147
|
"data-with-right-section":
|
|
140
148
|
restRecord.rightSection || !hideControls ? "true" : undefined,
|
|
141
149
|
}}
|
|
142
|
-
{...(sanitizedProps as unknown as MantineNumberInputProps)}
|
|
143
150
|
/>
|
|
144
151
|
}
|
|
145
152
|
/>
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
} from "@mantine/core";
|
|
10
10
|
import {
|
|
11
11
|
filterStylingProps,
|
|
12
|
+
withCallerOverride,
|
|
13
|
+
mergeClassNames,
|
|
12
14
|
type RecursicaOverStyled,
|
|
13
15
|
} from "../../utils/filterStylingProps";
|
|
14
16
|
import styles from "./Pagination.module.css";
|
|
@@ -42,25 +44,14 @@ function usePaginationClassNames(restRecord: Record<string, unknown>): {
|
|
|
42
44
|
className: string;
|
|
43
45
|
classNames: Partial<Record<string, string>>;
|
|
44
46
|
} {
|
|
45
|
-
const mergedClassNames
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
classNamesProp &&
|
|
54
|
-
typeof classNamesProp === "object" &&
|
|
55
|
-
!Array.isArray(classNamesProp)
|
|
56
|
-
) {
|
|
57
|
-
const o = classNamesProp as Partial<Record<string, string>>;
|
|
58
|
-
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
59
|
-
mergedClassNames.control = o.control
|
|
60
|
-
? `${styles.control} ${o.control}`
|
|
61
|
-
: styles.control;
|
|
62
|
-
mergedClassNames.dots = o.dots ? `${styles.dots} ${o.dots}` : styles.dots;
|
|
63
|
-
}
|
|
47
|
+
const mergedClassNames = mergeClassNames(
|
|
48
|
+
{
|
|
49
|
+
root: styles.root,
|
|
50
|
+
control: styles.control,
|
|
51
|
+
dots: styles.dots,
|
|
52
|
+
},
|
|
53
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
54
|
+
);
|
|
64
55
|
|
|
65
56
|
const classNameProp = restRecord.className as string | undefined;
|
|
66
57
|
const finalClass = classNameProp
|
|
@@ -80,9 +71,9 @@ const _PaginationRoot = forwardRef<HTMLDivElement, PaginationRootProps>(
|
|
|
80
71
|
return (
|
|
81
72
|
<MantinePagination.Root
|
|
82
73
|
ref={ref}
|
|
74
|
+
{...(sanitizedProps as MantinePaginationRootProps)}
|
|
83
75
|
className={stylingParams.className}
|
|
84
76
|
classNames={stylingParams.classNames}
|
|
85
|
-
{...(sanitizedProps as MantinePaginationRootProps)}
|
|
86
77
|
/>
|
|
87
78
|
);
|
|
88
79
|
},
|
|
@@ -97,13 +88,13 @@ const _PaginationNext = forwardRef<
|
|
|
97
88
|
ref,
|
|
98
89
|
) {
|
|
99
90
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
100
|
-
const
|
|
91
|
+
const computedIcon = withLabel ? NextWithLabel : undefined;
|
|
101
92
|
return (
|
|
102
93
|
<MantinePagination.Next
|
|
103
94
|
ref={ref}
|
|
104
|
-
data-variant="text"
|
|
105
|
-
icon={renderIcon as any}
|
|
106
95
|
{...sanitizedProps}
|
|
96
|
+
data-variant="text"
|
|
97
|
+
icon={withCallerOverride(computedIcon, icon) as any}
|
|
107
98
|
/>
|
|
108
99
|
);
|
|
109
100
|
});
|
|
@@ -117,13 +108,13 @@ const _PaginationPrevious = forwardRef<
|
|
|
117
108
|
ref,
|
|
118
109
|
) {
|
|
119
110
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
120
|
-
const
|
|
111
|
+
const computedIcon = withLabel ? PrevWithLabel : undefined;
|
|
121
112
|
return (
|
|
122
113
|
<MantinePagination.Previous
|
|
123
114
|
ref={ref}
|
|
124
|
-
data-variant="text"
|
|
125
|
-
icon={renderIcon as any}
|
|
126
115
|
{...sanitizedProps}
|
|
116
|
+
data-variant="text"
|
|
117
|
+
icon={withCallerOverride(computedIcon, icon) as any}
|
|
127
118
|
/>
|
|
128
119
|
);
|
|
129
120
|
});
|
|
@@ -137,13 +128,13 @@ const _PaginationFirst = forwardRef<
|
|
|
137
128
|
ref,
|
|
138
129
|
) {
|
|
139
130
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
140
|
-
const
|
|
131
|
+
const computedIcon = withLabel ? FirstWithLabel : undefined;
|
|
141
132
|
return (
|
|
142
133
|
<MantinePagination.First
|
|
143
134
|
ref={ref}
|
|
144
|
-
data-variant="text"
|
|
145
|
-
icon={renderIcon as any}
|
|
146
135
|
{...sanitizedProps}
|
|
136
|
+
data-variant="text"
|
|
137
|
+
icon={withCallerOverride(computedIcon, icon) as any}
|
|
147
138
|
/>
|
|
148
139
|
);
|
|
149
140
|
});
|
|
@@ -157,13 +148,13 @@ const _PaginationLast = forwardRef<
|
|
|
157
148
|
ref,
|
|
158
149
|
) {
|
|
159
150
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
160
|
-
const
|
|
151
|
+
const computedIcon = withLabel ? LastWithLabel : undefined;
|
|
161
152
|
return (
|
|
162
153
|
<MantinePagination.Last
|
|
163
154
|
ref={ref}
|
|
164
|
-
data-variant="text"
|
|
165
|
-
icon={renderIcon as any}
|
|
166
155
|
{...sanitizedProps}
|
|
156
|
+
data-variant="text"
|
|
157
|
+
icon={withCallerOverride(computedIcon, icon) as any}
|
|
167
158
|
/>
|
|
168
159
|
);
|
|
169
160
|
});
|
|
@@ -201,11 +192,11 @@ const _Pagination = forwardRef<HTMLDivElement, PaginationProps>(
|
|
|
201
192
|
return (
|
|
202
193
|
<MantinePagination
|
|
203
194
|
ref={ref}
|
|
195
|
+
{...labelsIcons}
|
|
196
|
+
{...(sanitizedProps as MantinePaginationProps)}
|
|
204
197
|
className={stylingParams.className}
|
|
205
198
|
classNames={stylingParams.classNames}
|
|
206
199
|
getControlProps={mergedGetControlProps}
|
|
207
|
-
{...labelsIcons}
|
|
208
|
-
{...(sanitizedProps as MantinePaginationProps)}
|
|
209
200
|
/>
|
|
210
201
|
);
|
|
211
202
|
},
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
} from "@mantine/core";
|
|
13
13
|
import {
|
|
14
14
|
filterStylingProps,
|
|
15
|
+
mergeClassNames,
|
|
16
|
+
withCallerOverride,
|
|
15
17
|
type RecursicaOverStyled,
|
|
16
18
|
} from "../../utils/filterStylingProps";
|
|
17
19
|
import styles from "./Panel.module.css";
|
|
@@ -68,38 +70,29 @@ const PanelBase = function Panel({
|
|
|
68
70
|
...rest
|
|
69
71
|
}: PanelProps) {
|
|
70
72
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
73
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
71
74
|
|
|
72
75
|
// Bind CSS module classes to Mantine's internal classNames API
|
|
73
|
-
const mergedClassNames
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
classNamesProp &&
|
|
84
|
-
typeof classNamesProp === "object" &&
|
|
85
|
-
!Array.isArray(classNamesProp)
|
|
86
|
-
) {
|
|
87
|
-
const o = classNamesProp as Record<string, string>;
|
|
88
|
-
Object.keys(o).forEach((key) => {
|
|
89
|
-
if (mergedClassNames[key]) {
|
|
90
|
-
mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
|
|
91
|
-
} else {
|
|
92
|
-
mergedClassNames[key] = o[key];
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
76
|
+
const mergedClassNames = mergeClassNames(
|
|
77
|
+
{
|
|
78
|
+
content: styles.content,
|
|
79
|
+
header: styles.header,
|
|
80
|
+
title: wrapHeaderText ? styles.titleTruncate : styles.title,
|
|
81
|
+
body: styles.body,
|
|
82
|
+
inner: styles.inner,
|
|
83
|
+
},
|
|
84
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
85
|
+
);
|
|
96
86
|
|
|
97
87
|
return (
|
|
98
88
|
<MantineDrawer
|
|
89
|
+
{...(sanitizedProps as unknown as MantineDrawerProps)}
|
|
99
90
|
position={placement} /* Recursica default: right; Mantine default: left */
|
|
100
91
|
keepMounted={keepMounted}
|
|
101
|
-
closeOnClickOutside={
|
|
102
|
-
|
|
92
|
+
closeOnClickOutside={withCallerOverride(
|
|
93
|
+
Boolean(rest.opened),
|
|
94
|
+
rest.closeOnClickOutside,
|
|
95
|
+
)}
|
|
103
96
|
classNames={mergedClassNames}
|
|
104
97
|
/>
|
|
105
98
|
);
|
|
@@ -130,7 +123,7 @@ export const PanelFooter = forwardRef<HTMLDivElement, PanelFooterProps>(
|
|
|
130
123
|
? `${styles.footer} ${classNameProp}`
|
|
131
124
|
: styles.footer;
|
|
132
125
|
|
|
133
|
-
return <div ref={ref} className={finalClassName}
|
|
126
|
+
return <div ref={ref} {...sanitizedProps} className={finalClassName} />;
|
|
134
127
|
},
|
|
135
128
|
);
|
|
136
129
|
PanelFooter.displayName = "PanelFooter";
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
} from "@mantine/core";
|
|
7
7
|
import {
|
|
8
8
|
filterStylingProps,
|
|
9
|
+
mergeClassNames,
|
|
10
|
+
withCallerOverride,
|
|
9
11
|
type RecursicaOverStyled,
|
|
10
12
|
} from "../../utils/filterStylingProps";
|
|
11
13
|
import styles from "./Popover.module.css";
|
|
@@ -47,54 +49,40 @@ export type PopoverProps = Omit<
|
|
|
47
49
|
const PopoverBase = function Popover({
|
|
48
50
|
overStyled = false,
|
|
49
51
|
withBeak = true,
|
|
52
|
+
position = "top", // Recursica default; Mantine defaults to "bottom"
|
|
50
53
|
...rest
|
|
51
54
|
}: PopoverProps) {
|
|
52
55
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
56
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
53
57
|
|
|
54
58
|
// Bind CSS module classes to Mantine's internal classNames API
|
|
55
|
-
const mergedClassNames
|
|
56
|
-
dropdown: styles.dropdown,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const classNamesProp = (sanitizedProps as Record<string, unknown>).classNames;
|
|
61
|
-
if (
|
|
62
|
-
classNamesProp &&
|
|
63
|
-
typeof classNamesProp === "object" &&
|
|
64
|
-
!Array.isArray(classNamesProp)
|
|
65
|
-
) {
|
|
66
|
-
const o = classNamesProp as Record<string, string>;
|
|
67
|
-
Object.keys(o).forEach((key) => {
|
|
68
|
-
if (mergedClassNames[key]) {
|
|
69
|
-
mergedClassNames[key] = `${mergedClassNames[key]} ${o[key]}`;
|
|
70
|
-
} else {
|
|
71
|
-
mergedClassNames[key] = o[key];
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
}
|
|
59
|
+
const mergedClassNames = mergeClassNames(
|
|
60
|
+
{ dropdown: styles.dropdown, arrow: styles.arrow },
|
|
61
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
62
|
+
);
|
|
75
63
|
|
|
76
64
|
// arrowSize must be a JS number prop — Mantine uses it for inline width/height
|
|
77
65
|
// and positioning offset (-arrowSize/2) calculations that cannot be CSS-driven.
|
|
78
66
|
// Default to 16 to match the Recursica beak-size token (16px).
|
|
79
|
-
const arrowSize =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
67
|
+
const arrowSize = withCallerOverride<number>(
|
|
68
|
+
16,
|
|
69
|
+
restRecord.arrowSize as number | undefined,
|
|
70
|
+
);
|
|
83
71
|
|
|
84
72
|
// Resolve withBeak (Recursica) vs withArrow (Mantine).
|
|
85
73
|
// withBeak takes precedence when both are provided.
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
| undefined
|
|
89
|
-
|
|
74
|
+
const resolvedWithArrow = withCallerOverride<boolean | undefined>(
|
|
75
|
+
withBeak,
|
|
76
|
+
restRecord.withArrow as boolean | undefined,
|
|
77
|
+
);
|
|
90
78
|
|
|
91
79
|
return (
|
|
92
80
|
<MantinePopover
|
|
93
|
-
|
|
81
|
+
{...(sanitizedProps as unknown as MantinePopoverProps)}
|
|
82
|
+
position={position}
|
|
94
83
|
arrowSize={arrowSize}
|
|
95
84
|
withArrow={resolvedWithArrow}
|
|
96
85
|
classNames={mergedClassNames}
|
|
97
|
-
{...(sanitizedProps as unknown as MantinePopoverProps)}
|
|
98
86
|
/>
|
|
99
87
|
);
|
|
100
88
|
};
|
|
@@ -133,8 +121,8 @@ const PopoverDropdown = function PopoverDropdown({
|
|
|
133
121
|
|
|
134
122
|
return (
|
|
135
123
|
<MantinePopover.Dropdown
|
|
136
|
-
className={classNameProp}
|
|
137
124
|
{...(sanitizedProps as unknown as MantinePopoverDropdownProps)}
|
|
125
|
+
className={classNameProp}
|
|
138
126
|
/>
|
|
139
127
|
);
|
|
140
128
|
};
|