@recursica/mantine-adapter 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/.storybook/commonArgTypes.ts +148 -0
  2. package/CHANGELOG.md +69 -0
  3. package/dist/mantine-adapter.cjs +1 -1
  4. package/dist/mantine-adapter.cjs.map +1 -1
  5. package/dist/mantine-adapter.css +1 -1
  6. package/dist/mantine-adapter.js +660 -586
  7. package/dist/mantine-adapter.js.map +1 -1
  8. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +1 -1
  9. package/dist/src/components/Chip/Chip.d.ts +14 -2
  10. package/package.json +5 -2
  11. package/src/OverStyling.stories.tsx +174 -0
  12. package/src/Version.stories.tsx +56 -0
  13. package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +48 -0
  14. package/src/components/Accordion/Accordion.module.css +261 -0
  15. package/src/components/Accordion/Accordion.stories.tsx +145 -0
  16. package/src/components/Accordion/Accordion.tsx +200 -0
  17. package/src/components/Accordion/index.ts +1 -0
  18. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
  19. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +73 -0
  20. package/src/components/AssistiveElement/AssistiveElement.tsx +91 -0
  21. package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +24 -0
  22. package/src/components/Avatar/Avatar.module.css +340 -0
  23. package/src/components/Avatar/Avatar.stories.tsx +102 -0
  24. package/src/components/Avatar/Avatar.tsx +100 -0
  25. package/src/components/Avatar/index.ts +1 -0
  26. package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
  27. package/src/components/Badge/Badge.module.css +124 -0
  28. package/src/components/Badge/Badge.stories.tsx +77 -0
  29. package/src/components/Badge/Badge.tsx +66 -0
  30. package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +14 -0
  31. package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
  32. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +77 -0
  33. package/src/components/Breadcrumb/Breadcrumb.tsx +64 -0
  34. package/src/components/Button/Button.module.css +275 -0
  35. package/src/components/Button/Button.stories.tsx +105 -0
  36. package/src/components/Button/Button.tsx +122 -0
  37. package/src/components/Button/IMPLEMENTATION_NOTES.md +45 -0
  38. package/src/components/Button/index.ts +1 -0
  39. package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +10 -0
  40. package/src/components/Card/Card.module.css +60 -0
  41. package/src/components/Card/Card.stories.tsx +141 -0
  42. package/src/components/Card/Card.tsx +176 -0
  43. package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
  44. package/src/components/Checkbox/Checkbox.module.css +204 -0
  45. package/src/components/Checkbox/Checkbox.stories.tsx +73 -0
  46. package/src/components/Checkbox/Checkbox.tsx +111 -0
  47. package/src/components/Checkbox/CheckboxGroup.stories.tsx +138 -0
  48. package/src/components/Checkbox/CheckboxGroup.tsx +140 -0
  49. package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +35 -0
  50. package/src/components/Chip/Chip.module.css +218 -0
  51. package/src/components/Chip/Chip.stories.tsx +115 -0
  52. package/src/components/Chip/Chip.tsx +143 -0
  53. package/src/components/DatePicker/DatePicker.stories.tsx +22 -0
  54. package/src/components/DatePicker/DatePicker.tsx +7 -0
  55. package/src/components/Dropdown/Dropdown.stories.tsx +22 -0
  56. package/src/components/Dropdown/Dropdown.tsx +7 -0
  57. package/src/components/FileInput/FileInput.stories.tsx +22 -0
  58. package/src/components/FileInput/FileInput.tsx +7 -0
  59. package/src/components/FileUpload/FileUpload.stories.tsx +22 -0
  60. package/src/components/FileUpload/FileUpload.tsx +7 -0
  61. package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
  62. package/src/components/FormControlWrapper/FormControlWrapper.module.css +46 -0
  63. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -0
  64. package/src/components/FormControlWrapper/FormControlWrapper.tsx +170 -0
  65. package/src/components/HoverCard/HoverCard.stories.tsx +17 -0
  66. package/src/components/HoverCard/HoverCard.tsx +7 -0
  67. package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
  68. package/src/components/Label/Label.module.css +177 -0
  69. package/src/components/Label/Label.stories.tsx +123 -0
  70. package/src/components/Label/Label.tsx +132 -0
  71. package/src/components/Label/index.ts +1 -0
  72. package/src/components/Link/Link.stories.tsx +17 -0
  73. package/src/components/Link/Link.tsx +7 -0
  74. package/src/components/Loader/Loader.stories.tsx +17 -0
  75. package/src/components/Loader/Loader.tsx +7 -0
  76. package/src/components/Menu/Menu.stories.tsx +17 -0
  77. package/src/components/Menu/Menu.tsx +7 -0
  78. package/src/components/Modal/Modal.stories.tsx +17 -0
  79. package/src/components/Modal/Modal.tsx +7 -0
  80. package/src/components/NumberInput/NumberInput.stories.tsx +22 -0
  81. package/src/components/NumberInput/NumberInput.tsx +7 -0
  82. package/src/components/Pagination/Pagination.stories.tsx +17 -0
  83. package/src/components/Pagination/Pagination.tsx +7 -0
  84. package/src/components/Panel/Panel.stories.tsx +17 -0
  85. package/src/components/Panel/Panel.tsx +7 -0
  86. package/src/components/Popover/Popover.stories.tsx +17 -0
  87. package/src/components/Popover/Popover.tsx +7 -0
  88. package/src/components/Radio/Radio.stories.tsx +22 -0
  89. package/src/components/Radio/Radio.tsx +7 -0
  90. package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
  91. package/src/components/ReadOnlyField/ReadOnlyField.module.css +49 -0
  92. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +120 -0
  93. package/src/components/ReadOnlyField/ReadOnlyField.tsx +75 -0
  94. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +46 -0
  95. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +85 -0
  96. package/src/components/ReadOnlyField/index.ts +3 -0
  97. package/src/components/Search/Search.stories.tsx +17 -0
  98. package/src/components/Search/Search.tsx +7 -0
  99. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +22 -0
  100. package/src/components/SegmentedControl/SegmentedControl.tsx +7 -0
  101. package/src/components/Slider/Slider.stories.tsx +22 -0
  102. package/src/components/Slider/Slider.tsx +7 -0
  103. package/src/components/Stepper/Stepper.stories.tsx +17 -0
  104. package/src/components/Stepper/Stepper.tsx +7 -0
  105. package/src/components/Switch/Switch.stories.tsx +22 -0
  106. package/src/components/Switch/Switch.tsx +7 -0
  107. package/src/components/Table/Table.stories.tsx +17 -0
  108. package/src/components/Table/Table.tsx +7 -0
  109. package/src/components/Tabs/Tabs.stories.tsx +17 -0
  110. package/src/components/Tabs/Tabs.tsx +7 -0
  111. package/src/components/Text/Text.stories.tsx +88 -0
  112. package/src/components/Text/Text.tsx +54 -0
  113. package/src/components/TextArea/TextArea.stories.tsx +22 -0
  114. package/src/components/TextArea/TextArea.tsx +7 -0
  115. package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
  116. package/src/components/TextField/TextField.module.css +225 -0
  117. package/src/components/TextField/TextField.stories.tsx +162 -0
  118. package/src/components/TextField/TextField.tsx +138 -0
  119. package/src/components/TimePicker/TimePicker.stories.tsx +22 -0
  120. package/src/components/TimePicker/TimePicker.tsx +7 -0
  121. package/src/components/Timeline/Timeline.stories.tsx +17 -0
  122. package/src/components/Timeline/Timeline.tsx +7 -0
  123. package/src/components/Title/Title.stories.tsx +63 -0
  124. package/src/components/Title/Title.tsx +45 -0
  125. package/src/components/Toast/Toast.stories.tsx +17 -0
  126. package/src/components/Toast/Toast.tsx +7 -0
  127. package/src/components/Tooltip/Tooltip.stories.tsx +17 -0
  128. package/src/components/Tooltip/Tooltip.tsx +7 -0
  129. package/src/components/TransferList/TransferList.stories.tsx +17 -0
  130. package/src/components/TransferList/TransferList.tsx +7 -0
  131. package/src/components/index.ts +39 -0
  132. package/src/env.d.ts +7 -0
  133. package/src/index.ts +3 -0
  134. package/src/types/index.ts +9 -0
  135. package/src/types/mantine.d.ts +7 -0
  136. package/src/types/scss-modules.d.ts +9 -0
  137. package/src/utils/ColorSchemeWrapper.tsx +27 -0
  138. package/src/utils/copyToClipboard.ts +36 -0
  139. package/src/utils/filterStylingProps.ts +139 -0
  140. package/src/utils/index.ts +1 -0
@@ -0,0 +1,45 @@
1
+ import { forwardRef } from "react";
2
+ import {
3
+ Title as MantineTitle,
4
+ type TitleProps as MantineTitleProps,
5
+ } from "@mantine/core";
6
+ import {
7
+ filterStylingProps,
8
+ type RecursicaOverStyled,
9
+ } from "../../utils/filterStylingProps";
10
+
11
+ export type RecursicaTitleProps = Omit<MantineTitleProps, "order"> & {
12
+ /**
13
+ * Enforces semantic HTML headers (h1-h6) cleanly bound to native typographic scaling variables in the design system.
14
+ */
15
+ order?: 1 | 2 | 3 | 4 | 5 | 6;
16
+ };
17
+
18
+ export type TitleProps = RecursicaOverStyled<RecursicaTitleProps>;
19
+
20
+ /**
21
+ * Enforces highly accessible structural markup utilizing semantic `<h1>` through `<h6>` tags securely bound directly to Recursica typographic scales.
22
+ */
23
+ export const Title = forwardRef<HTMLHeadingElement, TitleProps>(function Title(
24
+ { overStyled = false, order = 1, ...rest },
25
+ ref,
26
+ ) {
27
+ const sanitizedProps = filterStylingProps(rest, overStyled);
28
+ const classNameProp = (sanitizedProps as Record<string, unknown>)
29
+ .className as string | undefined;
30
+
31
+ const typographyClass = `recursica_brand_typography_h${order}`;
32
+ const mergedClassName = classNameProp
33
+ ? `${typographyClass} ${classNameProp}`
34
+ : typographyClass;
35
+
36
+ return (
37
+ <MantineTitle
38
+ ref={ref}
39
+ order={order}
40
+ className={mergedClassName}
41
+ {...(sanitizedProps as unknown as MantineTitleProps)}
42
+ />
43
+ );
44
+ });
45
+ Title.displayName = "Title";
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Toast } from "./Toast";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Toast> = {
6
+ title: "UI-Kit/🚧 Toast",
7
+ component: Toast,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Toast>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Toast" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type ToastProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Toast: React.FC<ToastProps> = (props) => {
6
+ return <div {...props}>Toast</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Tooltip } from "./Tooltip";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Tooltip> = {
6
+ title: "UI-Kit/🚧 Tooltip",
7
+ component: Tooltip,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Tooltip>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Tooltip" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type TooltipProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Tooltip: React.FC<TooltipProps> = (props) => {
6
+ return <div {...props}>Tooltip</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { TransferList } from "./TransferList";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof TransferList> = {
6
+ title: "UI-Kit/🚧 TransferList",
7
+ component: TransferList,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof TransferList>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="TransferList" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type TransferListProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const TransferList: React.FC<TransferListProps> = (props) => {
6
+ return <div {...props}>TransferList</div>;
7
+ };
@@ -0,0 +1,39 @@
1
+ export * from "./Accordion";
2
+ export * from "./Avatar";
3
+ export * from "./Badge/Badge";
4
+ export * from "./Breadcrumb/Breadcrumb";
5
+ export * from "./Button";
6
+ export * from "./Card/Card";
7
+ export * from "./Checkbox/Checkbox";
8
+ export * from "./Checkbox/CheckboxGroup";
9
+ export * from "./Chip/Chip";
10
+ export * from "./DatePicker/DatePicker";
11
+ export * from "./Dropdown/Dropdown";
12
+ export * from "./FileInput/FileInput";
13
+ export * from "./FileUpload/FileUpload";
14
+ export * from "./HoverCard/HoverCard";
15
+ export * from "./Link/Link";
16
+ export * from "./Loader/Loader";
17
+ export * from "./Label";
18
+ export * from "./Menu/Menu";
19
+ export * from "./Modal/Modal";
20
+ export * from "./NumberInput/NumberInput";
21
+ export * from "./Pagination/Pagination";
22
+ export * from "./Panel/Panel";
23
+ export * from "./Popover/Popover";
24
+ export * from "./Radio/Radio";
25
+ export * from "./ReadOnlyField";
26
+ export * from "./Search/Search";
27
+ export * from "./SegmentedControl/SegmentedControl";
28
+ export * from "./Slider/Slider";
29
+ export * from "./Stepper/Stepper";
30
+ export * from "./Switch/Switch";
31
+ export * from "./Table/Table";
32
+ export * from "./Tabs/Tabs";
33
+ export * from "./TextArea/TextArea";
34
+ export * from "./TextField/TextField";
35
+ export * from "./TimePicker/TimePicker";
36
+ export * from "./Timeline/Timeline";
37
+ export * from "./Toast/Toast";
38
+ export * from "./Tooltip/Tooltip";
39
+ export * from "./TransferList/TransferList";
package/src/env.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /// <reference types="vite/client" />
2
+ /// <reference types="vite-plugin-svgr/client" />
3
+
4
+ declare module "*.module.css" {
5
+ const classes: { readonly [key: string]: string };
6
+ export default classes;
7
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import "@recursica/adapter-common/style.css";
2
+ export * from "./components";
3
+ export * from "@recursica/adapter-common";
@@ -0,0 +1,9 @@
1
+ export interface ComboboxItem {
2
+ value: string;
3
+ label: string;
4
+ disabled?: boolean;
5
+ // icon?: IconName;
6
+ onClick?: () => void;
7
+ }
8
+
9
+ // Export other shared types here
@@ -0,0 +1,7 @@
1
+ import type { ComboboxItem as RecursicaComboboxItem } from "./index";
2
+ import "@mantine/core";
3
+
4
+ declare module "@mantine/core" {
5
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
6
+ export interface ComboboxItem extends RecursicaComboboxItem {}
7
+ }
@@ -0,0 +1,9 @@
1
+ declare module "*.scss" {
2
+ const content: { [className: string]: string };
3
+ export default content;
4
+ }
5
+
6
+ declare module "*.module.scss" {
7
+ const content: { [className: string]: string };
8
+ export default content;
9
+ }
@@ -0,0 +1,27 @@
1
+ import { useMantineColorScheme } from "@mantine/core";
2
+ import { useEffect } from "react";
3
+ import { addons } from "storybook/internal/preview-api";
4
+ import { DARK_MODE_EVENT_NAME } from "storybook-dark-mode";
5
+
6
+ const channel = addons.getChannel();
7
+
8
+ export function ColorSchemeWrapper({
9
+ children,
10
+ }: {
11
+ children: React.ReactNode;
12
+ }) {
13
+ const { setColorScheme } = useMantineColorScheme();
14
+
15
+ useEffect(() => {
16
+ const handleColorScheme = (value: boolean) => {
17
+ const theme = value ? "dark" : "light";
18
+ setColorScheme(theme);
19
+ document.documentElement.setAttribute("data-recursica-theme", theme);
20
+ };
21
+
22
+ channel.on(DARK_MODE_EVENT_NAME, handleColorScheme);
23
+ return () => channel.off(DARK_MODE_EVENT_NAME, handleColorScheme);
24
+ }, [setColorScheme]);
25
+
26
+ return <>{children}</>;
27
+ }
@@ -0,0 +1,36 @@
1
+ import React from "react";
2
+
3
+ /**
4
+ * Helper function for copy text to clipboard
5
+ * @param {string} textToCopy The text string for copying to the clipboard
6
+ * @param {element|node} componentRef The ref of the component that we want to trigger the copy
7
+ */
8
+ const copyToClipboard = (
9
+ textToCopy: string,
10
+ componentRef: React.RefObject<HTMLElement | null>,
11
+ ): Promise<void> => {
12
+ const currentFocus = document.activeElement as HTMLInputElement;
13
+ return new Promise((resolve, reject) => {
14
+ if (componentRef && componentRef.current) {
15
+ const textArea = document.createElement("textarea");
16
+ textArea.readOnly = true;
17
+ textArea.defaultValue = textToCopy;
18
+ componentRef.current.appendChild(textArea);
19
+ textArea.select();
20
+ const wasCopied = document.execCommand("copy");
21
+ componentRef.current.removeChild(textArea);
22
+ if (currentFocus) {
23
+ currentFocus.focus();
24
+ }
25
+ if (wasCopied) {
26
+ resolve();
27
+ } else {
28
+ reject(new Error("Failed to copy"));
29
+ }
30
+ } else {
31
+ reject(new Error("Copy area reference is not defined"));
32
+ }
33
+ });
34
+ };
35
+
36
+ export { copyToClipboard };
@@ -0,0 +1,139 @@
1
+ /**
2
+ * filterStylingProps
3
+ *
4
+ * This utility acts as the central gatekeeper for strict design-system adherence across
5
+ * all Recursica components mapped over Mantine.
6
+ *
7
+ * PHILOSOPHY:
8
+ * Recursica components are designed to be explicitly sandboxed tokens. Allowing external
9
+ * `className` or Mantine style system props (`bg`, `p`, etc.) breaks the design system by
10
+ * allowing developers to leak arbitrary designs into components.
11
+ *
12
+ * By default (`overStyled=false`), this utility actively prevents developers from overriding
13
+ * internal component styles (such as background, colors, typography, or internal classNames).
14
+ * It safely *permits* external layout overrides (like `margin` / `m`) so that components can
15
+ * easily be spaced alongside other DOM elements.
16
+ *
17
+ * If a developer passes `overStyled={true}`, this filter allows all styling properties to
18
+ * flow through to the underlying Mantine component natively, at the developer's own risk.
19
+ *
20
+ * @param props - The raw component props passed down to the wrapper
21
+ * @param overStyled - Boolean toggle to allow raw external styling. Defaults to false.
22
+ * @returns Sanitized component props safe for internal styling merging
23
+ */
24
+
25
+ export const BLOCKED_STYLING_KEYS = [
26
+ "className",
27
+ "classNames",
28
+ "style",
29
+ "styles",
30
+ "vars", // Internal structure hooks
31
+ "p",
32
+ "px",
33
+ "py",
34
+ "pt",
35
+ "pb",
36
+ "pl",
37
+ "pr", // Padding
38
+ "bg",
39
+ "c",
40
+ "opacity", // Color
41
+ "ff",
42
+ "fz",
43
+ "fw",
44
+ "lts",
45
+ "ta",
46
+ "lh",
47
+ "fs",
48
+ "tt",
49
+ "td", // Typography
50
+ "bd",
51
+ "bdw",
52
+ "bds",
53
+ "bdc",
54
+ "bdr", // Borders
55
+ "shadow", // Effects
56
+ "w",
57
+ "miw",
58
+ "maw",
59
+ "h",
60
+ "mih",
61
+ "mah", // Dimensions
62
+ ] as const;
63
+
64
+ export type BlockedStylingKeys = (typeof BLOCKED_STYLING_KEYS)[number];
65
+
66
+ export type RecursicaSpacing =
67
+ | "rec-none"
68
+ | "rec-sm"
69
+ | "rec-default"
70
+ | "rec-md"
71
+ | "rec-lg"
72
+ | "rec-xl"
73
+ | "rec-2xl";
74
+
75
+ const LAYOUT_PROPS = new Set([
76
+ "m",
77
+ "my",
78
+ "mx",
79
+ "mt",
80
+ "mb",
81
+ "ml",
82
+ "mr",
83
+ "gap",
84
+ "rowGap",
85
+ "columnGap",
86
+ "top",
87
+ "left",
88
+ "bottom",
89
+ "right",
90
+ ]);
91
+
92
+ const SPACING_MAP: Record<string, string> = {
93
+ "rec-none": "var(--recursica_brand_dimensions_general_none)",
94
+ "rec-sm": "var(--recursica_brand_dimensions_general_sm)",
95
+ "rec-default": "var(--recursica_brand_dimensions_general_default)",
96
+ "rec-md": "var(--recursica_brand_dimensions_general_md)",
97
+ "rec-lg": "var(--recursica_brand_dimensions_general_lg)",
98
+ "rec-xl": "var(--recursica_brand_dimensions_general_xl)",
99
+ "rec-2xl": "var(--recursica_brand_dimensions_general_2xl)",
100
+ };
101
+
102
+ export type ForbiddenStyles = { [K in BlockedStylingKeys]?: never };
103
+
104
+ export type RecursicaOverStyled<T> =
105
+ | (Omit<T, BlockedStylingKeys> &
106
+ ForbiddenStyles & { overStyled?: false | undefined })
107
+ | (T & { overStyled: true });
108
+
109
+ export function filterStylingProps<T extends Record<string, unknown>>(
110
+ props: T,
111
+ overStyled?: boolean,
112
+ ): Partial<T> {
113
+ if (overStyled) {
114
+ return props;
115
+ }
116
+
117
+ const sanitized = { ...props };
118
+
119
+ for (const prop of BLOCKED_STYLING_KEYS) {
120
+ if (prop in sanitized) {
121
+ delete sanitized[prop];
122
+ }
123
+ }
124
+
125
+ // Intercept Recursica spacing tokens for valid layout properties
126
+ for (const [key, value] of Object.entries(sanitized)) {
127
+ if (
128
+ typeof value === "string" &&
129
+ value.startsWith("rec-") &&
130
+ LAYOUT_PROPS.has(key)
131
+ ) {
132
+ if (value in SPACING_MAP) {
133
+ (sanitized as Record<string, unknown>)[key] = SPACING_MAP[value];
134
+ }
135
+ }
136
+ }
137
+
138
+ return sanitized;
139
+ }
@@ -0,0 +1 @@
1
+ export * from "./copyToClipboard";