@recursica/adapter-mantine-v8 1.0.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/.storybook/commonArgTypes.ts +148 -0
- package/ARCHITECTURE.md +18 -0
- package/CHANGELOG.md +688 -0
- package/LICENSE +21 -0
- package/OVERSTYLING.md +56 -0
- package/README.md +70 -0
- package/SETUP.md +93 -0
- package/USAGE.md +57 -0
- package/dist/adapter-mantine-v8.cjs +12 -0
- package/dist/adapter-mantine-v8.cjs.map +1 -0
- package/dist/adapter-mantine-v8.css +1 -0
- package/dist/adapter-mantine-v8.js +5759 -0
- package/dist/adapter-mantine-v8.js.map +1 -0
- package/dist/index.d.ts +2095 -0
- package/dist/test.html +1 -0
- package/dist/vite.svg +1 -0
- package/docs/PHILOSOPHY.md +39 -0
- package/llms.txt +74 -0
- package/package.json +131 -0
- package/recursica_brand.json +2677 -0
- package/recursica_tokens.json +799 -0
- package/recursica_ui-kit.json +14981 -0
- package/recursica_variables_scoped.css +30489 -0
- package/src/GlobalExemptions.modules.css +7 -0
- package/src/Introduction.stories.tsx +154 -0
- package/src/OverStyling.tsx +79 -0
- package/src/Version.tsx +44 -0
- package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +72 -0
- package/src/components/Accordion/Accordion.module.css +367 -0
- package/src/components/Accordion/Accordion.stories.tsx +189 -0
- package/src/components/Accordion/Accordion.test.tsx +1 -0
- package/src/components/Accordion/Accordion.tsx +220 -0
- package/src/components/Accordion/USAGE.md +51 -0
- package/src/components/Accordion/index.ts +1 -0
- package/src/components/AssistiveElement/ASSISTIVEELEMENT_IMPLEMENTATION_NOTES.md +45 -0
- package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +68 -0
- package/src/components/AssistiveElement/AssistiveElement.test.tsx +1 -0
- package/src/components/AssistiveElement/AssistiveElement.tsx +93 -0
- package/src/components/AssistiveElement/USAGE.md +36 -0
- package/src/components/AutoComplete/AUTOCOMPLETE_IMPLEMENTATION_NOTES.md +42 -0
- package/src/components/AutoComplete/AutoComplete.module.css +430 -0
- package/src/components/AutoComplete/AutoComplete.stories.tsx +336 -0
- package/src/components/AutoComplete/AutoComplete.test.tsx +1 -0
- package/src/components/AutoComplete/AutoComplete.tsx +179 -0
- package/src/components/AutoComplete/USAGE.md +80 -0
- package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +34 -0
- package/src/components/Avatar/Avatar.module.css +336 -0
- package/src/components/Avatar/Avatar.stories.tsx +92 -0
- package/src/components/Avatar/Avatar.test.tsx +1 -0
- package/src/components/Avatar/Avatar.tsx +108 -0
- package/src/components/Avatar/USAGE.md +38 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Badge/Badge.module.css +127 -0
- package/src/components/Badge/Badge.stories.tsx +78 -0
- package/src/components/Badge/Badge.test.tsx +1 -0
- package/src/components/Badge/Badge.tsx +64 -0
- package/src/components/Badge/USAGE.md +56 -0
- package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +47 -0
- package/src/components/Breadcrumb/Breadcrumb.module.css +48 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
- package/src/components/Breadcrumb/Breadcrumb.test.tsx +1 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +85 -0
- package/src/components/Breadcrumb/USAGE.md +55 -0
- package/src/components/Breadcrumb/markCurrentPageItem.test.ts +49 -0
- package/src/components/Button/Button.module.css +446 -0
- package/src/components/Button/Button.stories.tsx +196 -0
- package/src/components/Button/Button.styleIsolation.dom.test.tsx +98 -0
- package/src/components/Button/Button.tsx +184 -0
- package/src/components/Button/IMPLEMENTATION_NOTES.md +109 -0
- package/src/components/Button/USAGE.md +80 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +17 -0
- package/src/components/Card/Card.module.css +119 -0
- package/src/components/Card/Card.stories.tsx +131 -0
- package/src/components/Card/Card.test.tsx +1 -0
- package/src/components/Card/Card.tsx +248 -0
- package/src/components/Card/USAGE.md +63 -0
- package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/Checkbox/Checkbox.module.css +267 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +97 -0
- package/src/components/Checkbox/Checkbox.test.tsx +1 -0
- package/src/components/Checkbox/Checkbox.tsx +151 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +147 -0
- package/src/components/Checkbox/USAGE.md +48 -0
- package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +110 -0
- package/src/components/Chip/Chip.module.css +288 -0
- package/src/components/Chip/Chip.stories.tsx +128 -0
- package/src/components/Chip/Chip.test.tsx +1 -0
- package/src/components/Chip/Chip.tsx +157 -0
- package/src/components/Chip/USAGE.md +55 -0
- package/src/components/Container/CONTAINER_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Container/Container.module.css +7 -0
- package/src/components/Container/Container.stories.tsx +118 -0
- package/src/components/Container/Container.test.tsx +1 -0
- package/src/components/Container/Container.tsx +69 -0
- package/src/components/Container/USAGE.md +47 -0
- package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +31 -0
- package/src/components/DatePicker/DatePicker.icons.tsx +27 -0
- package/src/components/DatePicker/DatePicker.module.css +566 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +158 -0
- package/src/components/DatePicker/DatePicker.test.tsx +1 -0
- package/src/components/DatePicker/DatePicker.tsx +218 -0
- package/src/components/DatePicker/USAGE.md +49 -0
- package/src/components/Dropdown/BareDropdown.tsx +97 -0
- package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +12 -0
- package/src/components/Dropdown/Dropdown.module.css +477 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +252 -0
- package/src/components/Dropdown/Dropdown.test.tsx +1 -0
- package/src/components/Dropdown/Dropdown.tsx +213 -0
- package/src/components/Dropdown/USAGE.md +69 -0
- package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +153 -0
- package/src/components/FileInput/FileInput.module.css +280 -0
- package/src/components/FileInput/FileInput.stories.tsx +313 -0
- package/src/components/FileInput/FileInput.test.tsx +1 -0
- package/src/components/FileInput/FileInput.tsx +417 -0
- package/src/components/FileInput/USAGE.md +145 -0
- package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +244 -0
- package/src/components/FileUpload/FileUpload.module.css +205 -0
- package/src/components/FileUpload/FileUpload.stories.tsx +362 -0
- package/src/components/FileUpload/FileUpload.test.tsx +1 -0
- package/src/components/FileUpload/FileUpload.tsx +354 -0
- package/src/components/FileUpload/USAGE.md +199 -0
- package/src/components/Flex/FLEX_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Flex/Flex.module.css +7 -0
- package/src/components/Flex/Flex.stories.tsx +128 -0
- package/src/components/Flex/Flex.test.tsx +1 -0
- package/src/components/Flex/Flex.tsx +75 -0
- package/src/components/Flex/USAGE.md +48 -0
- package/src/components/FormControlLayout/FormControlLayout.module.css +90 -0
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +118 -0
- package/src/components/FormControlLayout/FormControlLayout.test.tsx +1 -0
- package/src/components/FormControlLayout/FormControlLayout.tsx +74 -0
- package/src/components/FormControlLayout/USAGE.md +40 -0
- package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +75 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +129 -0
- package/src/components/FormControlWrapper/FormControlWrapper.test.tsx +1 -0
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +151 -0
- package/src/components/FormControlWrapper/USAGE.md +47 -0
- package/src/components/Grid/GRID_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Grid/Grid.module.css +11 -0
- package/src/components/Grid/Grid.stories.tsx +206 -0
- package/src/components/Grid/Grid.test.tsx +1 -0
- package/src/components/Grid/Grid.tsx +140 -0
- package/src/components/Grid/USAGE.md +47 -0
- package/src/components/Group/GROUP_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Group/Group.module.css +7 -0
- package/src/components/Group/Group.stories.tsx +120 -0
- package/src/components/Group/Group.test.tsx +1 -0
- package/src/components/Group/Group.tsx +60 -0
- package/src/components/Group/USAGE.md +48 -0
- package/src/components/Heading/HEADING_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Heading/Heading.module.css +13 -0
- package/src/components/Heading/Heading.stories.tsx +50 -0
- package/src/components/Heading/Heading.test.tsx +1 -0
- package/src/components/Heading/Heading.tsx +52 -0
- package/src/components/Heading/USAGE.md +36 -0
- package/src/components/HoverCard/HOVERCARD_IMPLEMENTATION_NOTES.md +77 -0
- package/src/components/HoverCard/HoverCard.module.css +90 -0
- package/src/components/HoverCard/HoverCard.stories.tsx +172 -0
- package/src/components/HoverCard/HoverCard.test.tsx +1 -0
- package/src/components/HoverCard/HoverCard.tsx +133 -0
- package/src/components/HoverCard/USAGE.md +52 -0
- package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Label/Label.module.css +141 -0
- package/src/components/Label/Label.stories.tsx +131 -0
- package/src/components/Label/Label.test.tsx +1 -0
- package/src/components/Label/Label.tsx +113 -0
- package/src/components/Label/USAGE.md +47 -0
- package/src/components/Label/index.ts +1 -0
- package/src/components/Layer/USAGE.md +54 -0
- package/src/components/Link/IMPLEMENTATION_NOTES.md +19 -0
- package/src/components/Link/Link.module.css +110 -0
- package/src/components/Link/Link.stories.tsx +58 -0
- package/src/components/Link/Link.test.tsx +1 -0
- package/src/components/Link/Link.tsx +67 -0
- package/src/components/Link/USAGE.md +56 -0
- package/src/components/Link/index.ts +1 -0
- package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/Loader/Loader.animate.dom.test.tsx +82 -0
- package/src/components/Loader/Loader.module.css +63 -0
- package/src/components/Loader/Loader.stories.tsx +123 -0
- package/src/components/Loader/Loader.test.tsx +1 -0
- package/src/components/Loader/Loader.tsx +69 -0
- package/src/components/Loader/USAGE.md +44 -0
- package/src/components/Menu/MENU_IMPLEMENTATION_NOTES.md +88 -0
- package/src/components/Menu/Menu.module.css +280 -0
- package/src/components/Menu/Menu.stories.tsx +371 -0
- package/src/components/Menu/Menu.test.tsx +1 -0
- package/src/components/Menu/Menu.tsx +373 -0
- package/src/components/Menu/USAGE.md +55 -0
- package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +32 -0
- package/src/components/Modal/Modal.module.css +302 -0
- package/src/components/Modal/Modal.stories.tsx +105 -0
- package/src/components/Modal/Modal.test.tsx +1 -0
- package/src/components/Modal/Modal.tsx +368 -0
- package/src/components/Modal/USAGE.md +58 -0
- package/src/components/Modal/index.ts +1 -0
- package/src/components/NumberInput/NUMBER_INPUT_IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/NumberInput/NumberInput.module.css +302 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +96 -0
- package/src/components/NumberInput/NumberInput.test.tsx +1 -0
- package/src/components/NumberInput/NumberInput.tsx +157 -0
- package/src/components/NumberInput/USAGE.md +52 -0
- package/src/components/Pagination/IMPLEMENTATION_NOTES.md +16 -0
- package/src/components/Pagination/Pagination.icons.tsx +66 -0
- package/src/components/Pagination/Pagination.module.css +188 -0
- package/src/components/Pagination/Pagination.stories.tsx +48 -0
- package/src/components/Pagination/Pagination.test.tsx +1 -0
- package/src/components/Pagination/Pagination.tsx +265 -0
- package/src/components/Pagination/USAGE.md +36 -0
- package/src/components/Pagination/index.ts +5 -0
- package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +116 -0
- package/src/components/Panel/Panel.module.css +209 -0
- package/src/components/Panel/Panel.stories.tsx +227 -0
- package/src/components/Panel/Panel.test.tsx +1 -0
- package/src/components/Panel/Panel.tsx +269 -0
- package/src/components/Panel/USAGE.md +56 -0
- package/src/components/Popover/IMPLEMENTATION_NOTES.md +77 -0
- package/src/components/Popover/Popover.module.css +86 -0
- package/src/components/Popover/Popover.stories.tsx +133 -0
- package/src/components/Popover/Popover.test.tsx +1 -0
- package/src/components/Popover/Popover.tsx +142 -0
- package/src/components/Popover/USAGE.md +61 -0
- package/src/components/Popover/index.ts +1 -0
- package/src/components/Radio/Radio.module.css +231 -0
- package/src/components/Radio/Radio.stories.tsx +93 -0
- package/src/components/Radio/Radio.test.tsx +1 -0
- package/src/components/Radio/Radio.tsx +168 -0
- package/src/components/Radio/RadioGroup.stories.tsx +117 -0
- package/src/components/Radio/RadioGroup.tsx +124 -0
- package/src/components/Radio/USAGE.md +36 -0
- package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
- package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +54 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +163 -0
- package/src/components/ReadOnlyField/ReadOnlyField.test.tsx +1 -0
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +114 -0
- package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
- package/src/components/ReadOnlyField/USAGE.md +44 -0
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
- package/src/components/ReadOnlyField/index.ts +5 -0
- package/src/components/RecursicaThemeProvider/USAGE.md +60 -0
- package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/SegmentedControl/SegmentedControl.module.css +185 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +106 -0
- package/src/components/SegmentedControl/SegmentedControl.test.tsx +1 -0
- package/src/components/SegmentedControl/SegmentedControl.tsx +110 -0
- package/src/components/SegmentedControl/USAGE.md +55 -0
- package/src/components/Slider/IMPLEMENTATION_NOTES.md +92 -0
- package/src/components/Slider/Slider.module.css +588 -0
- package/src/components/Slider/Slider.stories.tsx +282 -0
- package/src/components/Slider/Slider.test.tsx +1 -0
- package/src/components/Slider/Slider.tsx +391 -0
- package/src/components/Slider/USAGE.md +56 -0
- package/src/components/Stack/STACK_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Stack/Stack.module.css +7 -0
- package/src/components/Stack/Stack.stories.tsx +108 -0
- package/src/components/Stack/Stack.test.tsx +1 -0
- package/src/components/Stack/Stack.tsx +62 -0
- package/src/components/Stack/USAGE.md +48 -0
- package/src/components/Stepper/IMPLEMENTATION_NOTES.md +28 -0
- package/src/components/Stepper/Stepper.module.css +404 -0
- package/src/components/Stepper/Stepper.stories.tsx +148 -0
- package/src/components/Stepper/Stepper.test.tsx +1 -0
- package/src/components/Stepper/Stepper.tsx +93 -0
- package/src/components/Stepper/USAGE.md +41 -0
- package/src/components/Switch/SWITCH_IMPLEMENTATION_NOTES.md +64 -0
- package/src/components/Switch/Switch.module.css +279 -0
- package/src/components/Switch/Switch.stories.tsx +114 -0
- package/src/components/Switch/Switch.test.tsx +1 -0
- package/src/components/Switch/Switch.tsx +177 -0
- package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
- package/src/components/Switch/SwitchGroup.tsx +127 -0
- package/src/components/Switch/USAGE.md +42 -0
- package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +78 -0
- package/src/components/Table/Table.icons.tsx +40 -0
- package/src/components/Table/Table.module.css +444 -0
- package/src/components/Table/Table.stories.tsx +140 -0
- package/src/components/Table/Table.test.tsx +1 -0
- package/src/components/Table/Table.tsx +243 -0
- package/src/components/Table/USAGE.md +78 -0
- package/src/components/Tabs/IMPLEMENTATION_NOTES.md +27 -0
- package/src/components/Tabs/Tabs.module.css +591 -0
- package/src/components/Tabs/Tabs.stories.tsx +154 -0
- package/src/components/Tabs/Tabs.test.tsx +1 -0
- package/src/components/Tabs/Tabs.tsx +114 -0
- package/src/components/Tabs/USAGE.md +45 -0
- package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +12 -0
- package/src/components/Text/Text.module.css +13 -0
- package/src/components/Text/Text.stories.tsx +75 -0
- package/src/components/Text/Text.test.tsx +1 -0
- package/src/components/Text/Text.tsx +53 -0
- package/src/components/Text/USAGE.md +40 -0
- package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +7 -0
- package/src/components/TextArea/TextArea.module.css +183 -0
- package/src/components/TextArea/TextArea.stories.tsx +94 -0
- package/src/components/TextArea/TextArea.test.tsx +1 -0
- package/src/components/TextArea/TextArea.tsx +137 -0
- package/src/components/TextArea/USAGE.md +48 -0
- package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
- package/src/components/TextField/TextField.module.css +264 -0
- package/src/components/TextField/TextField.stories.tsx +162 -0
- package/src/components/TextField/TextField.test.tsx +1 -0
- package/src/components/TextField/TextField.tsx +139 -0
- package/src/components/TextField/USAGE.md +44 -0
- package/src/components/TimePicker/TIMEPICKER_IMPLEMENTATION_NOTES.md +119 -0
- package/src/components/TimePicker/TimePicker.module.css +291 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +141 -0
- package/src/components/TimePicker/TimePicker.test.tsx +1 -0
- package/src/components/TimePicker/TimePicker.tsx +304 -0
- package/src/components/TimePicker/USAGE.md +57 -0
- package/src/components/Timeline/TIMELINE_IMPLEMENTATION_NOTES.md +13 -0
- package/src/components/Timeline/Timeline.module.css +373 -0
- package/src/components/Timeline/Timeline.stories.tsx +128 -0
- package/src/components/Timeline/Timeline.test.tsx +1 -0
- package/src/components/Timeline/Timeline.tsx +73 -0
- package/src/components/Timeline/TimelineItem.tsx +79 -0
- package/src/components/Timeline/USAGE.md +49 -0
- package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +39 -0
- package/src/components/Toast/Toast.module.css +184 -0
- package/src/components/Toast/Toast.stories.tsx +67 -0
- package/src/components/Toast/Toast.test.tsx +1 -0
- package/src/components/Toast/Toast.tsx +82 -0
- package/src/components/Toast/USAGE.md +50 -0
- package/src/components/Toast/index.ts +1 -0
- package/src/components/Tooltip/TOOLTIP_IMPLEMENTATION_NOTES.md +85 -0
- package/src/components/Tooltip/Tooltip.module.css +91 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +165 -0
- package/src/components/Tooltip/Tooltip.test.tsx +1 -0
- package/src/components/Tooltip/Tooltip.tsx +117 -0
- package/src/components/Tooltip/USAGE.md +80 -0
- package/src/components/TransferList/TRANSFERLIST_IMPLEMENTATION_NOTES.md +111 -0
- package/src/components/TransferList/TransferList.module.css +182 -0
- package/src/components/TransferList/TransferList.stories.tsx +121 -0
- package/src/components/TransferList/TransferList.test.tsx +1 -0
- package/src/components/TransferList/TransferList.tsx +419 -0
- package/src/components/TransferList/USAGE.md +77 -0
- package/src/components/Tree/IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Tree/Tree.module.css +232 -0
- package/src/components/Tree/Tree.stories.tsx +104 -0
- package/src/components/Tree/Tree.test.tsx +1 -0
- package/src/components/Tree/Tree.tsx +220 -0
- package/src/components/Tree/USAGE.md +96 -0
- package/src/components/Tree/index.ts +1 -0
- package/src/components/index.ts +52 -0
- package/src/env.d.ts +7 -0
- package/src/index.ts +179 -0
- package/src/types/index.ts +9 -0
- package/src/types/mantine.d.ts +7 -0
- package/src/types/scss-modules.d.ts +9 -0
- package/src/utils/ColorSchemeWrapper.tsx +27 -0
- package/src/utils/RequireAccessibleLabel.ts +1 -0
- package/src/utils/copyToClipboard.ts +36 -0
- package/src/utils/filterStylingProps.test.ts +85 -0
- package/src/utils/filterStylingProps.ts +150 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/renderRichOption.tsx +65 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future FormControlWrapper component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import React, { forwardRef, useId } from "react";
|
|
2
|
+
import { type InputWrapperProps } from "@mantine/core";
|
|
3
|
+
import {
|
|
4
|
+
filterStylingProps,
|
|
5
|
+
type RecursicaOverStyled,
|
|
6
|
+
} from "../../utils/filterStylingProps";
|
|
7
|
+
import { Label } from "../Label/Label";
|
|
8
|
+
import { FormControlLayout } from "../FormControlLayout/FormControlLayout";
|
|
9
|
+
import { AssistiveElement } from "../AssistiveElement/AssistiveElement";
|
|
10
|
+
import styles from "./FormControlWrapper.module.css";
|
|
11
|
+
|
|
12
|
+
import { type RecursicaFormControlWrapperProps } from "@recursica/adapter-common";
|
|
13
|
+
export type { RecursicaFormControlWrapperProps };
|
|
14
|
+
|
|
15
|
+
export type FormControlWrapperProps = RecursicaOverStyled<
|
|
16
|
+
Omit<InputWrapperProps, "labelProps" | "inputWrapperOrder"> &
|
|
17
|
+
RecursicaFormControlWrapperProps
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
export const FormControlWrapper = forwardRef<
|
|
21
|
+
HTMLDivElement,
|
|
22
|
+
FormControlWrapperProps
|
|
23
|
+
>(function FormControlWrapper(
|
|
24
|
+
{
|
|
25
|
+
formLayout,
|
|
26
|
+
labelSize,
|
|
27
|
+
labelAlignment,
|
|
28
|
+
labelOptionalText,
|
|
29
|
+
labelWithEditIcon,
|
|
30
|
+
labelActionArea,
|
|
31
|
+
onLabelEditClick,
|
|
32
|
+
|
|
33
|
+
label,
|
|
34
|
+
description,
|
|
35
|
+
assistiveText,
|
|
36
|
+
assistiveWithIcon = true,
|
|
37
|
+
controlMaxWidth,
|
|
38
|
+
controlMinWidth,
|
|
39
|
+
error,
|
|
40
|
+
required,
|
|
41
|
+
withAsterisk,
|
|
42
|
+
id: userProvidedId,
|
|
43
|
+
children,
|
|
44
|
+
className,
|
|
45
|
+
overStyled = false,
|
|
46
|
+
labelElement, // Extracted safely preventing bleeding into HTML domains
|
|
47
|
+
...rest
|
|
48
|
+
},
|
|
49
|
+
ref,
|
|
50
|
+
) {
|
|
51
|
+
// Generate a reliable ID to map the Label's HTML context down to the component array natively.
|
|
52
|
+
const generatedId = useId();
|
|
53
|
+
const id = userProvidedId || `recursica-fc-${generatedId}`;
|
|
54
|
+
const labelId = `${id}-label`;
|
|
55
|
+
|
|
56
|
+
// Evaluate explicit assistive fallbacks ensuring assistiveText correctly prioritizes natively over underlying Mantine configurations!
|
|
57
|
+
const resolvedAssistive = assistiveText || description;
|
|
58
|
+
const assistiveId = resolvedAssistive ? `${id}-assistive` : undefined;
|
|
59
|
+
const errorId = error ? `${id}-error` : undefined;
|
|
60
|
+
|
|
61
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
62
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
63
|
+
|
|
64
|
+
const classNameProp =
|
|
65
|
+
className || (restRecord.className as string | undefined);
|
|
66
|
+
const rootClass = styles.root;
|
|
67
|
+
const finalClass = classNameProp
|
|
68
|
+
? `${rootClass} ${classNameProp}`
|
|
69
|
+
: rootClass;
|
|
70
|
+
|
|
71
|
+
// Clone ARIA identifiers directly back down into the nested children wrapper so screen-readers natively hook the external strings.
|
|
72
|
+
// `id` is cloned down here too — the label's `htmlFor` below only resolves to the field's
|
|
73
|
+
// native `label.control` when the field itself actually carries this id.
|
|
74
|
+
const content = React.isValidElement(children)
|
|
75
|
+
? React.cloneElement(
|
|
76
|
+
children as React.ReactElement<Record<string, unknown>>,
|
|
77
|
+
{
|
|
78
|
+
...(!(children.props as Record<string, unknown>)["id"] ? { id } : {}),
|
|
79
|
+
"aria-labelledby": labelId,
|
|
80
|
+
...(resolvedAssistive &&
|
|
81
|
+
!(children.props as Record<string, unknown>)["aria-describedby"]
|
|
82
|
+
? { "aria-describedby": assistiveId }
|
|
83
|
+
: {}),
|
|
84
|
+
...(error &&
|
|
85
|
+
!(children.props as Record<string, unknown>)["aria-errormessage"]
|
|
86
|
+
? { "aria-errormessage": errorId }
|
|
87
|
+
: {}),
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
: children;
|
|
91
|
+
|
|
92
|
+
const labelNode = label ? (
|
|
93
|
+
<Label
|
|
94
|
+
id={labelId}
|
|
95
|
+
htmlFor={id} // Native label/control association — must not also be set on the label's own id
|
|
96
|
+
labelAlignment={labelAlignment}
|
|
97
|
+
labelOptionalText={labelOptionalText}
|
|
98
|
+
labelWithEditIcon={labelWithEditIcon}
|
|
99
|
+
labelActionArea={labelActionArea}
|
|
100
|
+
onLabelEditClick={onLabelEditClick}
|
|
101
|
+
required={withAsterisk ?? required}
|
|
102
|
+
// Manually propagate relevant structural logic if underlying groups dictate Label to act as generic wrapper
|
|
103
|
+
{...(labelElement === "div" ? { as: "div" } : {})}
|
|
104
|
+
>
|
|
105
|
+
{label}
|
|
106
|
+
</Label>
|
|
107
|
+
) : undefined;
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<FormControlLayout
|
|
111
|
+
ref={ref}
|
|
112
|
+
className={finalClass}
|
|
113
|
+
formLayout={formLayout}
|
|
114
|
+
labelSize={labelSize}
|
|
115
|
+
controlMaxWidth={controlMaxWidth}
|
|
116
|
+
controlMinWidth={controlMinWidth}
|
|
117
|
+
leftSection={labelNode}
|
|
118
|
+
{...restRecord}
|
|
119
|
+
>
|
|
120
|
+
{/*
|
|
121
|
+
The Core Input Wrapper & Controls
|
|
122
|
+
Nakedly inject the actual field elements alongside natively bridged Assistive components mapped dynamically.
|
|
123
|
+
*/}
|
|
124
|
+
<div className={styles.inputSection}>
|
|
125
|
+
{content}
|
|
126
|
+
|
|
127
|
+
{error && (
|
|
128
|
+
<AssistiveElement
|
|
129
|
+
id={errorId}
|
|
130
|
+
assistiveVariant="error"
|
|
131
|
+
assistiveWithIcon={assistiveWithIcon}
|
|
132
|
+
>
|
|
133
|
+
{error}
|
|
134
|
+
</AssistiveElement>
|
|
135
|
+
)}
|
|
136
|
+
|
|
137
|
+
{!error && resolvedAssistive && (
|
|
138
|
+
<AssistiveElement
|
|
139
|
+
id={assistiveId}
|
|
140
|
+
assistiveVariant="help"
|
|
141
|
+
assistiveWithIcon={assistiveWithIcon}
|
|
142
|
+
>
|
|
143
|
+
{resolvedAssistive}
|
|
144
|
+
</AssistiveElement>
|
|
145
|
+
)}
|
|
146
|
+
</div>
|
|
147
|
+
</FormControlLayout>
|
|
148
|
+
);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
FormControlWrapper.displayName = "FormControlWrapper";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# FormControlWrapper - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `FormControlWrapper` component in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { FormControlWrapper } from "@recursica/adapter-mantine-v8";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { FormControlWrapper } from "@recursica/adapter-mantine-v8";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<FormControlWrapper label="Email Address" required error="Invalid email">
|
|
24
|
+
<input type="email" />
|
|
25
|
+
</FormControlWrapper>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 3. Design System Integration
|
|
33
|
+
|
|
34
|
+
All Recursica components in the `@recursica/adapter-mantine-v8` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
35
|
+
|
|
36
|
+
> [!IMPORTANT]
|
|
37
|
+
>
|
|
38
|
+
> - **Anti-override protection**: Rogues style injections (like inline `style` or arbitrary `className`) are automatically blocked by our prop layer unless `overStyled={true}` is explicitly provided.
|
|
39
|
+
> - **No Direct Layers**: Do not pass a `layer` prop to this component. To place it on a specific visual layer, wrap it in a `<Layer layer={0|1|2|3}>` component natively.
|
|
40
|
+
> - **Variables and Theming**: Styling is entirely determined by local CSS variables defined in `recursica_variables_scoped.css` and mapped in the component's CSS module.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 4. Notes
|
|
45
|
+
|
|
46
|
+
- `FormControlWrapper` renders the label, error, and help text around the child input; screen-reader associations between the input and its assistive text are handled automatically.
|
|
47
|
+
- The wrapper stretches to fill its container by default. If the wrapped input has its own maximum width, pass a matching `--form-control-max-width` CSS variable via the `style` prop so the label and assistive text align to the same width as the input.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Grid Implementation Notes
|
|
2
|
+
|
|
3
|
+
The `Grid` component is a generic 12-column (by default) layout wrapper mapped directly to Mantine's `Grid`/`Grid.Col`. It requires no custom logical layouts or CSS workarounds — Mantine handles column geometry, breakpoints, and wrapping natively.
|
|
4
|
+
|
|
5
|
+
Per the layout-components rule (no formal Recursica common props definition — these simply pass through the underlying kit's own props), `Grid` and `Grid.Col` are typed directly off Mantine's own `GridProps`/`GridColProps` with no Recursica-specific prop renaming. The public prop for spacing between columns is Mantine's own `gutter` (previously renamed to `gap` for cross-component consistency — that rename has been reverted since it wasn't a real Mantine prop). `gutter` still accepts `rec-*` spacing tokens, resolved via `mapLayoutProps`, the same utility used elsewhere.
|
|
6
|
+
|
|
7
|
+
`Grid.Col`'s `span`, `offset`, `order`, `visibleFrom`, and `hiddenFrom` props are passed straight through to Mantine's `Grid.Col` unchanged, using Mantine's own breakpoint scale (`xs`/`sm`/`md`/`lg`/`xl` — there is no `base` breakpoint in Mantine; `xs` is the smallest).
|
|
8
|
+
|
|
9
|
+
Like the other primitive layout components, `Grid` and `Grid.Col` use `WithRecursicaSpacing<T>` rather than `RecursicaOverStyled<T>` and are listed in the "Primitive Layout Components Exemption" section of `OVERSTYLING.md`.
|
|
10
|
+
|
|
11
|
+
## Added `ResponsiveSizes` story (2026-08-30, source-of-truth audit)
|
|
12
|
+
|
|
13
|
+
mui-adapter has a `ui-kit-grid--responsive-sizes` story with no counterpart here — its `story
|
|
14
|
+
parity with source of truth` check would otherwise fail for mui-adapter. Added an equivalent
|
|
15
|
+
`ResponsiveSizes` story using Mantine's own `span` prop (Mantine's `Grid.Col` has no `size` prop
|
|
16
|
+
— see the naming-divergence note above and mui-adapter's own `IMPLEMENTATION_NOTES.md`). This is
|
|
17
|
+
functionally identical to the existing `ResponsiveSpans` story above; it exists purely so
|
|
18
|
+
mui-adapter's differently-named story id has a source-of-truth golden to diff against.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/* HARDCODED VALUES:
|
|
2
|
+
* None. This is a generic grid layout wrapper.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.root {
|
|
6
|
+
/* Mantine handles the grid geometry (columns, gutter, spans) natively. No intrinsic design-system styles required for pure layout wrappers. */
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.col {
|
|
10
|
+
/* Mantine handles column sizing (span, offset, order, visibleFrom/hiddenFrom) natively. */
|
|
11
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Grid } from "./Grid";
|
|
4
|
+
import { Card } from "../Card/Card";
|
|
5
|
+
import { Text } from "../Text/Text";
|
|
6
|
+
|
|
7
|
+
type GridStoryProps = React.ComponentProps<typeof Grid>;
|
|
8
|
+
|
|
9
|
+
const meta: Meta<GridStoryProps> = {
|
|
10
|
+
title: "UI-Kit/Grid",
|
|
11
|
+
component: Grid,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
"Grid is a 12-column (by default) responsive grid layout that maps directly to Mantine's Grid/Grid.Col, providing column spans, offsets, ordering, and breakpoint-based visibility.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
gutter: "rec-default",
|
|
23
|
+
columns: 12,
|
|
24
|
+
grow: false,
|
|
25
|
+
},
|
|
26
|
+
argTypes: {
|
|
27
|
+
gutter: {
|
|
28
|
+
control: "select",
|
|
29
|
+
options: [
|
|
30
|
+
"rec-none",
|
|
31
|
+
"rec-sm",
|
|
32
|
+
"rec-default",
|
|
33
|
+
"rec-md",
|
|
34
|
+
"rec-lg",
|
|
35
|
+
"rec-xl",
|
|
36
|
+
"rec-2xl",
|
|
37
|
+
],
|
|
38
|
+
description: "Gutter between columns",
|
|
39
|
+
},
|
|
40
|
+
columns: {
|
|
41
|
+
control: "number",
|
|
42
|
+
description: "Number of columns in each row",
|
|
43
|
+
},
|
|
44
|
+
grow: {
|
|
45
|
+
control: "boolean",
|
|
46
|
+
description: "Columns in the last row expand to fill available space",
|
|
47
|
+
},
|
|
48
|
+
justify: {
|
|
49
|
+
control: "select",
|
|
50
|
+
options: [
|
|
51
|
+
"flex-start",
|
|
52
|
+
"center",
|
|
53
|
+
"flex-end",
|
|
54
|
+
"space-between",
|
|
55
|
+
"space-around",
|
|
56
|
+
],
|
|
57
|
+
description: "Justify-content property",
|
|
58
|
+
},
|
|
59
|
+
align: {
|
|
60
|
+
control: "select",
|
|
61
|
+
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
62
|
+
description: "Align-items property",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default meta;
|
|
68
|
+
|
|
69
|
+
type Story = StoryObj<GridStoryProps>;
|
|
70
|
+
|
|
71
|
+
const Swatch = ({ children }: { children: React.ReactNode }) => (
|
|
72
|
+
<Card>
|
|
73
|
+
<Card.Content>
|
|
74
|
+
<Text>{children}</Text>
|
|
75
|
+
</Card.Content>
|
|
76
|
+
</Card>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
export const Default: Story = {
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
81
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
82
|
+
<Grid {...args}>
|
|
83
|
+
<Grid.Col span={4}>
|
|
84
|
+
<Swatch>span 4</Swatch>
|
|
85
|
+
</Grid.Col>
|
|
86
|
+
<Grid.Col span={4}>
|
|
87
|
+
<Swatch>span 4</Swatch>
|
|
88
|
+
</Grid.Col>
|
|
89
|
+
<Grid.Col span={4}>
|
|
90
|
+
<Swatch>span 4</Swatch>
|
|
91
|
+
</Grid.Col>
|
|
92
|
+
</Grid>
|
|
93
|
+
),
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const ResponsiveSpans: Story = {
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
98
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
99
|
+
<Grid {...args}>
|
|
100
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
101
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
102
|
+
</Grid.Col>
|
|
103
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
104
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
105
|
+
</Grid.Col>
|
|
106
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
107
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
108
|
+
</Grid.Col>
|
|
109
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
110
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
111
|
+
</Grid.Col>
|
|
112
|
+
</Grid>
|
|
113
|
+
),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Mirrors mui-adapter's `ResponsiveSizes` story (same breakpoints/content) under mantine's own
|
|
117
|
+
// prop name — Mantine's Grid.Col has no `size` prop, only `span`, which is what `ResponsiveSpans`
|
|
118
|
+
// above already exercises. This one exists purely so mui-adapter's `responsive-sizes` story id
|
|
119
|
+
// has a source-of-truth counterpart to diff against (see Grid's IMPLEMENTATION_NOTES.md).
|
|
120
|
+
export const ResponsiveSizes: Story = {
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
122
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
123
|
+
<Grid {...args}>
|
|
124
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
125
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
126
|
+
</Grid.Col>
|
|
127
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
128
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
129
|
+
</Grid.Col>
|
|
130
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
131
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
132
|
+
</Grid.Col>
|
|
133
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>
|
|
134
|
+
<Swatch>xs 12 / sm 6 / md 3</Swatch>
|
|
135
|
+
</Grid.Col>
|
|
136
|
+
</Grid>
|
|
137
|
+
),
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const Offset: Story = {
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
142
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
143
|
+
<Grid {...args}>
|
|
144
|
+
<Grid.Col span={4} offset={4}>
|
|
145
|
+
<Swatch>span 4, offset 4</Swatch>
|
|
146
|
+
</Grid.Col>
|
|
147
|
+
<Grid.Col span={4}>
|
|
148
|
+
<Swatch>span 4</Swatch>
|
|
149
|
+
</Grid.Col>
|
|
150
|
+
</Grid>
|
|
151
|
+
),
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const Grow: Story = {
|
|
155
|
+
args: {
|
|
156
|
+
grow: true,
|
|
157
|
+
},
|
|
158
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
159
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
160
|
+
<Grid {...args}>
|
|
161
|
+
<Grid.Col span={3}>
|
|
162
|
+
<Swatch>span 3</Swatch>
|
|
163
|
+
</Grid.Col>
|
|
164
|
+
<Grid.Col span={3}>
|
|
165
|
+
<Swatch>span 3</Swatch>
|
|
166
|
+
</Grid.Col>
|
|
167
|
+
<Grid.Col span={3}>
|
|
168
|
+
<Swatch>span 3 (grows to fill row)</Swatch>
|
|
169
|
+
</Grid.Col>
|
|
170
|
+
</Grid>
|
|
171
|
+
),
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export const CustomColumnCount: Story = {
|
|
175
|
+
args: {
|
|
176
|
+
columns: 6,
|
|
177
|
+
},
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
179
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
180
|
+
<Grid {...args}>
|
|
181
|
+
<Grid.Col span={2}>
|
|
182
|
+
<Swatch>span 2 of 6</Swatch>
|
|
183
|
+
</Grid.Col>
|
|
184
|
+
<Grid.Col span={2}>
|
|
185
|
+
<Swatch>span 2 of 6</Swatch>
|
|
186
|
+
</Grid.Col>
|
|
187
|
+
<Grid.Col span={2}>
|
|
188
|
+
<Swatch>span 2 of 6</Swatch>
|
|
189
|
+
</Grid.Col>
|
|
190
|
+
</Grid>
|
|
191
|
+
),
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const VisibleHiddenFrom: Story = {
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
196
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
197
|
+
<Grid {...args}>
|
|
198
|
+
<Grid.Col span={6} hiddenFrom="sm">
|
|
199
|
+
<Swatch>hidden from sm and up</Swatch>
|
|
200
|
+
</Grid.Col>
|
|
201
|
+
<Grid.Col span={6} visibleFrom="sm">
|
|
202
|
+
<Swatch>visible from sm and up</Swatch>
|
|
203
|
+
</Grid.Col>
|
|
204
|
+
</Grid>
|
|
205
|
+
),
|
|
206
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Grid component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Grid as MantineGrid,
|
|
4
|
+
type GridProps as MantineGridProps,
|
|
5
|
+
type GridColProps as MantineGridColProps,
|
|
6
|
+
createPolymorphicComponent,
|
|
7
|
+
} from "@mantine/core";
|
|
8
|
+
import {
|
|
9
|
+
mapLayoutProps,
|
|
10
|
+
type WithRecursicaSpacing,
|
|
11
|
+
} from "../../utils/filterStylingProps";
|
|
12
|
+
import styles from "./Grid.module.css";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Grid layout wrapper.
|
|
16
|
+
*
|
|
17
|
+
* Note: Unlike complex UI components, primitive layout components (Flex, Stack, Group, Container, Grid)
|
|
18
|
+
* DO NOT use the `RecursicaOverStyled` gatekeeper. Developers must be able to freely pass
|
|
19
|
+
* width, height, padding, margins, and flexbox alignment props to construct structural layouts.
|
|
20
|
+
*
|
|
21
|
+
* No formal Recursica prop contract here: this simply passes through Mantine's own
|
|
22
|
+
* `GridProps` (gutter/grow/columns/justify/align are all native to Mantine), layered only
|
|
23
|
+
* with rec- spacing token support via `WithRecursicaSpacing`.
|
|
24
|
+
*/
|
|
25
|
+
export type GridProps = WithRecursicaSpacing<MantineGridProps>;
|
|
26
|
+
|
|
27
|
+
const _Grid = forwardRef<HTMLDivElement, GridProps>(function Grid(
|
|
28
|
+
{ children, gutter = "rec-default", ...rest },
|
|
29
|
+
ref,
|
|
30
|
+
) {
|
|
31
|
+
const mergedClassNames: Partial<Record<string, string>> = {
|
|
32
|
+
root: styles.root,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const classNamesProp = rest.classNames;
|
|
36
|
+
if (
|
|
37
|
+
classNamesProp &&
|
|
38
|
+
typeof classNamesProp === "object" &&
|
|
39
|
+
!Array.isArray(classNamesProp)
|
|
40
|
+
) {
|
|
41
|
+
const o = classNamesProp as Partial<Record<string, string>>;
|
|
42
|
+
mergedClassNames.root = o.root ? `${styles.root} ${o.root}` : styles.root;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const classNameProp = rest.className as string | undefined;
|
|
46
|
+
const finalClass = classNameProp
|
|
47
|
+
? `${styles.root} ${classNameProp}`
|
|
48
|
+
: styles.root;
|
|
49
|
+
|
|
50
|
+
const { gutter: mappedGutter, ...mappedRest } = mapLayoutProps({
|
|
51
|
+
gutter,
|
|
52
|
+
...rest,
|
|
53
|
+
} as Record<string, unknown>);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<MantineGrid
|
|
57
|
+
ref={ref}
|
|
58
|
+
gutter={mappedGutter as MantineGridProps["gutter"]}
|
|
59
|
+
className={finalClass}
|
|
60
|
+
classNames={mergedClassNames}
|
|
61
|
+
{...(mappedRest as unknown as Omit<MantineGridProps, "gutter">)}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</MantineGrid>
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
_Grid.displayName = "Grid";
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Recursica Grid layout wrapper.
|
|
71
|
+
*
|
|
72
|
+
* Supports polymorphism via the `component` prop for custom element rendering.
|
|
73
|
+
* @example
|
|
74
|
+
* ```tsx
|
|
75
|
+
* <Grid gap="rec-default">
|
|
76
|
+
* <Grid.Col span={6}>Half width</Grid.Col>
|
|
77
|
+
* <Grid.Col span={6}>Half width</Grid.Col>
|
|
78
|
+
* </Grid>
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
const GridBase = createPolymorphicComponent<"div", GridProps>(_Grid);
|
|
82
|
+
|
|
83
|
+
// ============================================================
|
|
84
|
+
// GRID.COL
|
|
85
|
+
// ============================================================
|
|
86
|
+
|
|
87
|
+
export type GridColProps = WithRecursicaSpacing<MantineGridColProps>;
|
|
88
|
+
|
|
89
|
+
const _GridCol = forwardRef<HTMLDivElement, GridColProps>(function GridCol(
|
|
90
|
+
{ children, ...rest },
|
|
91
|
+
ref,
|
|
92
|
+
) {
|
|
93
|
+
const mergedClassNames: Partial<Record<string, string>> = {
|
|
94
|
+
col: styles.col,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const classNamesProp = rest.classNames;
|
|
98
|
+
if (
|
|
99
|
+
classNamesProp &&
|
|
100
|
+
typeof classNamesProp === "object" &&
|
|
101
|
+
!Array.isArray(classNamesProp)
|
|
102
|
+
) {
|
|
103
|
+
const o = classNamesProp as Partial<Record<string, string>>;
|
|
104
|
+
mergedClassNames.col = o.col ? `${styles.col} ${o.col}` : styles.col;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const classNameProp = rest.className as string | undefined;
|
|
108
|
+
const finalClass = classNameProp
|
|
109
|
+
? `${styles.col} ${classNameProp}`
|
|
110
|
+
: styles.col;
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<MantineGrid.Col
|
|
114
|
+
ref={ref}
|
|
115
|
+
className={finalClass}
|
|
116
|
+
classNames={mergedClassNames}
|
|
117
|
+
{...(mapLayoutProps(
|
|
118
|
+
rest as Record<string, unknown>,
|
|
119
|
+
) as unknown as MantineGridColProps)}
|
|
120
|
+
>
|
|
121
|
+
{children}
|
|
122
|
+
</MantineGrid.Col>
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
_GridCol.displayName = "GridCol";
|
|
126
|
+
|
|
127
|
+
export const GridCol = createPolymorphicComponent<"div", GridColProps>(
|
|
128
|
+
_GridCol,
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
// ============================================================
|
|
132
|
+
// DOT NOTATION EXPORT
|
|
133
|
+
// ============================================================
|
|
134
|
+
|
|
135
|
+
type GridComponent = typeof GridBase & {
|
|
136
|
+
Col: typeof GridCol;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const Grid = GridBase as GridComponent;
|
|
140
|
+
Grid.Col = GridCol;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Grid - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Grid` component in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Grid } from "@recursica/adapter-mantine-v8";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Grid } from "@recursica/adapter-mantine-v8";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<Grid gutter="rec-default">
|
|
24
|
+
<Grid.Col span={6}>Half width</Grid.Col>
|
|
25
|
+
<Grid.Col span={{ xs: 12, sm: 6, md: 3 }}>Responsive width</Grid.Col>
|
|
26
|
+
</Grid>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 3. Design System Integration
|
|
34
|
+
|
|
35
|
+
All Recursica components in the `@recursica/adapter-mantine-v8` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
36
|
+
|
|
37
|
+
> [!IMPORTANT]
|
|
38
|
+
>
|
|
39
|
+
> - **Anti-override protection**: `Grid` is a primitive layout component (see [OVERSTYLING.md](../../../OVERSTYLING.md)), so standard Mantine layout props pass through freely without needing `overStyled`.
|
|
40
|
+
> - **No Direct Layers**: Do not pass a `layer` prop to this component. To place it on a specific visual layer, wrap it in a `<Layer layer={0|1|2|3}>` component natively.
|
|
41
|
+
> - **Variables and Theming**: Spacing is entirely determined by the `rec-*` token scale, mapped transparently to standard Mantine gutter values.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 4. Key Integration Features & Constraints
|
|
46
|
+
|
|
47
|
+
The `Grid` component maps directly to Mantine's `Grid`/`Grid.Col` with no Recursica-specific prop renaming — `gutter`, `columns`, `grow`, `justify`, `align` on `Grid`, and `span`, `offset`, `order`, `visibleFrom`, `hiddenFrom` on `Grid.Col` all match Mantine's own naming and accept the same shapes, including per-breakpoint objects (`{ xs, sm, md, lg, xl }`). `gutter` additionally accepts `rec-*` spacing tokens.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Group Implementation Notes
|
|
2
|
+
|
|
3
|
+
The `Group` component is a generic flex layout wrapper mapped directly to Mantine's `Group`.
|
|
4
|
+
It currently does not require any custom logical layouts or CSS workarounds since it serves only to organize layout structure, and doesn't enforce any strict design-system token styling itself. All gap, align, wrap, and justify properties pass safely through via the `filterStylingProps` layout-property allowance.
|