@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,93 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React, { forwardRef } from "react";
|
|
3
|
+
import { type ReadOnlyFieldType } from "@recursica/adapter-common";
|
|
4
|
+
import {
|
|
5
|
+
FormControlWrapper,
|
|
6
|
+
type FormControlWrapperProps,
|
|
7
|
+
} from "../FormControlWrapper/FormControlWrapper";
|
|
8
|
+
import { ReadOnlyField } from "./ReadOnlyField";
|
|
9
|
+
|
|
10
|
+
export interface WithReadOnlyWrapperProps
|
|
11
|
+
extends Omit<FormControlWrapperProps, "children" | "overStyled"> {
|
|
12
|
+
/** Injects whether the field defaults to reading mode natively */
|
|
13
|
+
readOnly?: boolean;
|
|
14
|
+
/** Explicit React component directly overtaking the baseline text renderer when read-only mode is active */
|
|
15
|
+
readOnlyComponent?: React.ElementType<any>;
|
|
16
|
+
/** Custom renderer explicitly responsible for formatting missing/empty value mappings (overriding default 'N/A') */
|
|
17
|
+
emptyValueComponent?: React.ElementType<{ value?: any }>;
|
|
18
|
+
/** The full native props dictionary securely forwarded into the custom readOnlyComponent if active */
|
|
19
|
+
readOnlyNativeProps?: any;
|
|
20
|
+
/** Instructs the underlying generic ReadOnlyField which raw visual structure to bridge automatically */
|
|
21
|
+
readOnlyType?: ReadOnlyFieldType;
|
|
22
|
+
/** The isolated raw data value intercepted explicitly into the ReadOnly formatters */
|
|
23
|
+
readOnlyValue?: any;
|
|
24
|
+
/** Safely enables deep Mantine overrides transparently bypassing block filters */
|
|
25
|
+
overStyled?: boolean;
|
|
26
|
+
/** The nested active node dynamically exposed exclusively when read-only bounds are disabled */
|
|
27
|
+
activeComponent: React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Universal execution barrier trapping readOnly states globally.
|
|
32
|
+
* Natively delegates active logic down avoiding duplicative internal component bindings dynamically.
|
|
33
|
+
*/
|
|
34
|
+
export const WithReadOnlyWrapper = forwardRef<
|
|
35
|
+
HTMLDivElement,
|
|
36
|
+
WithReadOnlyWrapperProps
|
|
37
|
+
>(function WithReadOnlyWrapper(
|
|
38
|
+
{
|
|
39
|
+
readOnly,
|
|
40
|
+
readOnlyComponent,
|
|
41
|
+
readOnlyType = "text",
|
|
42
|
+
readOnlyValue,
|
|
43
|
+
readOnlyNativeProps,
|
|
44
|
+
emptyValueComponent,
|
|
45
|
+
activeComponent,
|
|
46
|
+
overStyled,
|
|
47
|
+
onLabelEditClick,
|
|
48
|
+
...wrapperProps
|
|
49
|
+
},
|
|
50
|
+
ref,
|
|
51
|
+
) {
|
|
52
|
+
if (readOnly) {
|
|
53
|
+
if (readOnlyComponent) {
|
|
54
|
+
const ReadOnlyComponent = readOnlyComponent;
|
|
55
|
+
return (
|
|
56
|
+
<FormControlWrapper
|
|
57
|
+
ref={ref}
|
|
58
|
+
{...wrapperProps}
|
|
59
|
+
onLabelEditClick={onLabelEditClick}
|
|
60
|
+
overStyled={overStyled as true}
|
|
61
|
+
>
|
|
62
|
+
<ReadOnlyComponent {...readOnlyNativeProps} />
|
|
63
|
+
</FormControlWrapper>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<ReadOnlyField
|
|
69
|
+
ref={ref}
|
|
70
|
+
{...wrapperProps}
|
|
71
|
+
type={readOnlyType}
|
|
72
|
+
value={readOnlyValue}
|
|
73
|
+
emptyValueComponent={emptyValueComponent}
|
|
74
|
+
onLabelEditClick={onLabelEditClick}
|
|
75
|
+
overStyled={overStyled as true}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Active Standard Execution natively forwarding bound children implicitly
|
|
81
|
+
return (
|
|
82
|
+
<FormControlWrapper
|
|
83
|
+
ref={ref}
|
|
84
|
+
{...wrapperProps}
|
|
85
|
+
onLabelEditClick={onLabelEditClick}
|
|
86
|
+
overStyled={overStyled as true}
|
|
87
|
+
>
|
|
88
|
+
{activeComponent}
|
|
89
|
+
</FormControlWrapper>
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
WithReadOnlyWrapper.displayName = "WithReadOnlyWrapper";
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# RecursicaThemeProvider - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use `RecursicaThemeProvider` in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
> [!NOTE] > `RecursicaThemeProvider` is defined once in `@recursica/adapter-common` and re-exported here so it shares the exact same behavior across every Recursica adapter.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Import Reference
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { RecursicaThemeProvider } from "@recursica/adapter-mantine-v8";
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 2. Basic Example
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { MantineProvider } from "@mantine/core";
|
|
21
|
+
import { RecursicaThemeProvider } from "@recursica/adapter-mantine-v8";
|
|
22
|
+
|
|
23
|
+
function App() {
|
|
24
|
+
return (
|
|
25
|
+
<MantineProvider>
|
|
26
|
+
<RecursicaThemeProvider theme="light">
|
|
27
|
+
{/* Your App Components */}
|
|
28
|
+
</RecursicaThemeProvider>
|
|
29
|
+
</MantineProvider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
By default, `RecursicaThemeProvider` also wraps `children` in a base [`Layer`](../Layer/USAGE.md) (`layer={0}`), so surface/border/elevation variables resolve immediately — no separate `Layer` needed for the page background.
|
|
35
|
+
|
|
36
|
+
If you want to place the base layer yourself (e.g. to use `contentsOnly`, or to control exactly where layer 0 starts in the tree), opt out with `initLayer0={false}`:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { RecursicaThemeProvider, Layer } from "@recursica/adapter-mantine-v8";
|
|
40
|
+
|
|
41
|
+
<RecursicaThemeProvider theme="light" initLayer0={false}>
|
|
42
|
+
<Layer layer={0}>{/* Your App Components */}</Layer>
|
|
43
|
+
</RecursicaThemeProvider>;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 3. Design System Integration
|
|
49
|
+
|
|
50
|
+
> [!IMPORTANT]
|
|
51
|
+
>
|
|
52
|
+
> - **Required for setup**: `RecursicaThemeProvider` must wrap your entire application, once, near the root. See [SETUP.md](../../../SETUP.md) for the full setup sequence.
|
|
53
|
+
> - **`initLayer0` (default `true`)**: Automatically wraps `children` in a layer-0 [`Layer`](../Layer/USAGE.md). `RecursicaThemeProvider` itself only sets `data-recursica-theme` (`"light"` or `"dark"`, defaults to `"light"`) on `document.documentElement` — without a `Layer` in the tree (either the automatic one or one you add yourself with `initLayer0={false}`), none of Recursica's surface CSS variables resolve.
|
|
54
|
+
> - **Runtime theme switching**: Changing the `theme` prop re-runs the effect and updates `data-recursica-theme` immediately, so you can drive light/dark switching from application state.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 4. Key Integration Features & Constraints
|
|
59
|
+
|
|
60
|
+
`RecursicaThemeProvider` also wires up the `overStyled` development-mode visual auditing helper (see [OVERSTYLING.md](../../../OVERSTYLING.md)) — `recursica.toggleOverStyled()` in the browser console only works once this provider has mounted.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# SegmentedControl Implementation Notes
|
|
2
|
+
|
|
3
|
+
## 1. Stripping Mantine's Native Variants and Sizes
|
|
4
|
+
|
|
5
|
+
The Figma design tokens for the SegmentedControl component do not define nested layers of variants (such as `solid`, `outline`) or specific sizing steps (`xs`, `sm`, etc.). They are defined globally. Therefore, we explicitly `Omit` the standard `variant`, `size`, `radius`, and `color` props from the generic Mantine `SegmentedControlProps` interface.
|
|
6
|
+
|
|
7
|
+
## 2. Hardcoded Overrides for Figma Strictness
|
|
8
|
+
|
|
9
|
+
Mantine injects inline hover styles on `.label` (specifically, adding a subtle gray background when hovering). Since Recursica defines explicit transparent or specifically-driven hover states, we use `!important` tags within `SegmentedControl.module.css` for background and typography overriding.
|
|
10
|
+
|
|
11
|
+
## 3. Divider Separators
|
|
12
|
+
|
|
13
|
+
Mantine uses an `::before` pseudo-element on the `.control` block to draw standard visual separators between adjacent elements. Instead of stripping this functionality out, we hook directly into the pseudo-element and override its `background-color` with `--recursica_ui-kit_components_segmented-control_properties_colors_divider-color`.
|
|
14
|
+
|
|
15
|
+
## 4. Indicator Mapping
|
|
16
|
+
|
|
17
|
+
The moving active background element (`.indicator`) is decoupled from the actual text label. It is styled natively with its own background color, border size, and elevation shadow variables to match the exact visual parity of a "floating active chip" as defined in the Recursica properties map.
|
|
18
|
+
|
|
19
|
+
## 5. Per-item `icon`
|
|
20
|
+
|
|
21
|
+
`RecursicaSegmentedControlProps.data` objects accept an optional `icon`. Mantine's own `data` item has no such slot, so this component `Omit`s Mantine's native `data` type and composes `icon`+`label` into a single `label` ReactNode before handing it to Mantine — Mantine's own `innerLabel` wrapper then lays it out using the icon-size/gap tokens already present in `SegmentedControl.module.css`.
|
|
22
|
+
|
|
23
|
+
## 6. Whole-control `disabled`
|
|
24
|
+
|
|
25
|
+
`RecursicaSegmentedControlProps.disabled` was previously typed `never` and stripped at runtime. It's now a real `boolean?`, passed straight through to Mantine's own native `disabled` — Mantine's `SegmentedControl` already disables every item when set. Per-item disabling via `data[].disabled` continues to work independently of it.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/* HARDCODED VALUES:
|
|
2
|
+
- border-style: solid; on container and indicator
|
|
3
|
+
- background-color: transparent; on label hover (overriding Mantine)
|
|
4
|
+
- Scope prefix .root to enforce Figma tokens over Mantine's inline calculation without using !important
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* EXEMPTIONS:
|
|
8
|
+
- The generic, non-state-specific segmented-control-item border-radius is ignored: the
|
|
9
|
+
selected/unselected state-specific border-radius tokens below already cover both states an
|
|
10
|
+
item can be in. */
|
|
11
|
+
/* recursica-ignore: --recursica_ui-kit_components_segmented-control-item_properties_item_border-radius */
|
|
12
|
+
|
|
13
|
+
.root {
|
|
14
|
+
background-color: var(
|
|
15
|
+
--recursica_ui-kit_components_segmented-control_properties_colors_background-color
|
|
16
|
+
);
|
|
17
|
+
border: var(
|
|
18
|
+
--recursica_ui-kit_components_segmented-control_properties_border-size
|
|
19
|
+
)
|
|
20
|
+
solid
|
|
21
|
+
var(
|
|
22
|
+
--recursica_ui-kit_components_segmented-control_properties_colors_border-color
|
|
23
|
+
);
|
|
24
|
+
border-radius: var(
|
|
25
|
+
--recursica_ui-kit_components_segmented-control_properties_border-radius
|
|
26
|
+
);
|
|
27
|
+
padding: var(
|
|
28
|
+
--recursica_ui-kit_components_segmented-control_properties_padding-vertical
|
|
29
|
+
)
|
|
30
|
+
var(
|
|
31
|
+
--recursica_ui-kit_components_segmented-control_properties_padding-horizontal
|
|
32
|
+
);
|
|
33
|
+
box-shadow: var(
|
|
34
|
+
--recursica_ui-kit_components_segmented-control_properties_elevation
|
|
35
|
+
);
|
|
36
|
+
gap: var(--recursica_ui-kit_components_segmented-control_properties_item-gap);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.root .label {
|
|
40
|
+
padding-left: var(
|
|
41
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_padding-horizontal
|
|
42
|
+
);
|
|
43
|
+
padding-right: var(
|
|
44
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_padding-horizontal
|
|
45
|
+
);
|
|
46
|
+
height: var(
|
|
47
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_height
|
|
48
|
+
);
|
|
49
|
+
border-radius: var(
|
|
50
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_border-radius
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
border: var(
|
|
54
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_border-size
|
|
55
|
+
)
|
|
56
|
+
solid
|
|
57
|
+
var(
|
|
58
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_colors_border-color
|
|
59
|
+
);
|
|
60
|
+
background-color: var(
|
|
61
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_colors_background-color
|
|
62
|
+
);
|
|
63
|
+
box-shadow: var(
|
|
64
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_elevation
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
font-family: var(
|
|
68
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_font-family
|
|
69
|
+
);
|
|
70
|
+
font-size: var(
|
|
71
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_font-size
|
|
72
|
+
);
|
|
73
|
+
font-style: var(
|
|
74
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_font-style
|
|
75
|
+
);
|
|
76
|
+
font-weight: var(
|
|
77
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_font-weight
|
|
78
|
+
);
|
|
79
|
+
letter-spacing: var(
|
|
80
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_letter-spacing
|
|
81
|
+
);
|
|
82
|
+
line-height: var(
|
|
83
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_line-height
|
|
84
|
+
);
|
|
85
|
+
text-decoration: var(
|
|
86
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_text-decoration
|
|
87
|
+
);
|
|
88
|
+
text-transform: var(
|
|
89
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_text_text-transform
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
color: var(
|
|
93
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_unselected_properties_colors_text-color
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
display: flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
justify-content: center;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Mantine natively wraps label contents in an innerLabel span */
|
|
102
|
+
.root .label :global(.mantine-SegmentedControl-innerLabel) {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
justify-content: center;
|
|
106
|
+
gap: var(
|
|
107
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_icon-text-gap
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.root .label svg {
|
|
112
|
+
width: var(
|
|
113
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_icon-size
|
|
114
|
+
);
|
|
115
|
+
height: var(
|
|
116
|
+
--recursica_ui-kit_components_segmented-control-item_properties_item_icon-size
|
|
117
|
+
);
|
|
118
|
+
flex-shrink: 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Mantine adds a background on hover, we must strictly strip it */
|
|
122
|
+
.root .label:hover {
|
|
123
|
+
background-color: transparent;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Mantine adds separators via ::before on the .control */
|
|
127
|
+
.root .control::before {
|
|
128
|
+
background-color: var(
|
|
129
|
+
--recursica_ui-kit_components_segmented-control_properties_colors_divider-color
|
|
130
|
+
);
|
|
131
|
+
width: var(
|
|
132
|
+
--recursica_ui-kit_components_segmented-control_properties_divider-size
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Indicator (the moving selected block) */
|
|
137
|
+
.root .indicator {
|
|
138
|
+
background-color: var(
|
|
139
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_colors_background-color
|
|
140
|
+
);
|
|
141
|
+
border: var(
|
|
142
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_border-size
|
|
143
|
+
)
|
|
144
|
+
solid
|
|
145
|
+
var(
|
|
146
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_colors_border-color
|
|
147
|
+
);
|
|
148
|
+
box-shadow: var(
|
|
149
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_elevation
|
|
150
|
+
);
|
|
151
|
+
border-radius: var(
|
|
152
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_border-radius
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Selected label text color override */
|
|
157
|
+
.root .control[data-active] .label {
|
|
158
|
+
color: var(
|
|
159
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_colors_text-color
|
|
160
|
+
);
|
|
161
|
+
font-family: var(
|
|
162
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_font-family
|
|
163
|
+
);
|
|
164
|
+
font-size: var(
|
|
165
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_font-size
|
|
166
|
+
);
|
|
167
|
+
font-style: var(
|
|
168
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_font-style
|
|
169
|
+
);
|
|
170
|
+
font-weight: var(
|
|
171
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_font-weight
|
|
172
|
+
);
|
|
173
|
+
letter-spacing: var(
|
|
174
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_letter-spacing
|
|
175
|
+
);
|
|
176
|
+
line-height: var(
|
|
177
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_line-height
|
|
178
|
+
);
|
|
179
|
+
text-decoration: var(
|
|
180
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_text-decoration
|
|
181
|
+
);
|
|
182
|
+
text-transform: var(
|
|
183
|
+
--recursica_ui-kit_components_segmented-control-item_variants_selection-states_selected_properties_text_text-transform
|
|
184
|
+
);
|
|
185
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { SegmentedControl } from "./SegmentedControl";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof SegmentedControl> = {
|
|
5
|
+
title: "UI-Kit/SegmentedControl",
|
|
6
|
+
component: SegmentedControl,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
"SegmentedControl provides a linear set of two or more segments, each of which functions as a mutually exclusive button.",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
argTypes: {
|
|
17
|
+
orientation: {
|
|
18
|
+
control: "radio",
|
|
19
|
+
options: ["horizontal", "vertical"],
|
|
20
|
+
},
|
|
21
|
+
fullWidth: {
|
|
22
|
+
control: "boolean",
|
|
23
|
+
},
|
|
24
|
+
disabled: {
|
|
25
|
+
control: "boolean",
|
|
26
|
+
},
|
|
27
|
+
data: { table: { disable: true } },
|
|
28
|
+
defaultChecked: { table: { disable: true } },
|
|
29
|
+
},
|
|
30
|
+
} satisfies Meta<typeof SegmentedControl>;
|
|
31
|
+
|
|
32
|
+
export default meta;
|
|
33
|
+
type Story = StoryObj<typeof SegmentedControl>;
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
data: ["React", "Angular", "Vue", "Svelte"],
|
|
38
|
+
orientation: "horizontal",
|
|
39
|
+
fullWidth: false,
|
|
40
|
+
},
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
42
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
43
|
+
return <SegmentedControl {...args} />;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const FullWidth: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
data: ["Daily", "Weekly", "Monthly"],
|
|
50
|
+
fullWidth: true,
|
|
51
|
+
},
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
53
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
54
|
+
return <SegmentedControl {...args} />;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const Vertical: Story = {
|
|
59
|
+
args: {
|
|
60
|
+
data: ["Option 1", "Option 2", "Option 3"],
|
|
61
|
+
orientation: "vertical",
|
|
62
|
+
},
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
64
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
65
|
+
return <SegmentedControl {...args} />;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const Disabled: Story = {
|
|
70
|
+
args: {
|
|
71
|
+
data: ["Preview", "Code", "Edit"],
|
|
72
|
+
disabled: true,
|
|
73
|
+
},
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
75
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
76
|
+
return <SegmentedControl {...args} />;
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const CheckIcon = () => (
|
|
81
|
+
<svg
|
|
82
|
+
viewBox="0 0 24 24"
|
|
83
|
+
fill="none"
|
|
84
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
85
|
+
stroke="currentColor"
|
|
86
|
+
strokeWidth="2"
|
|
87
|
+
strokeLinecap="round"
|
|
88
|
+
strokeLinejoin="round"
|
|
89
|
+
>
|
|
90
|
+
<polyline points="20 6 9 17 4 12" />
|
|
91
|
+
</svg>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
export const WithIcons: Story = {
|
|
95
|
+
args: {
|
|
96
|
+
data: [
|
|
97
|
+
{ value: "daily", label: "Daily", icon: <CheckIcon /> },
|
|
98
|
+
{ value: "weekly", label: "Weekly", icon: <CheckIcon /> },
|
|
99
|
+
{ value: "monthly", label: "Monthly", icon: <CheckIcon /> },
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
103
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
104
|
+
return <SegmentedControl {...args} />;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future SegmentedControl component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
SegmentedControl as MantineSegmentedControl,
|
|
4
|
+
type SegmentedControlProps as MantineSegmentedControlProps,
|
|
5
|
+
} from "@mantine/core";
|
|
6
|
+
import {
|
|
7
|
+
filterStylingProps,
|
|
8
|
+
mergeClassNames,
|
|
9
|
+
type RecursicaOverStyled,
|
|
10
|
+
} from "../../utils/filterStylingProps";
|
|
11
|
+
import styles from "./SegmentedControl.module.css";
|
|
12
|
+
|
|
13
|
+
import { type RecursicaSegmentedControlProps } from "@recursica/adapter-common";
|
|
14
|
+
|
|
15
|
+
export type SegmentedControlProps = RecursicaOverStyled<
|
|
16
|
+
Omit<
|
|
17
|
+
MantineSegmentedControlProps,
|
|
18
|
+
| "variant"
|
|
19
|
+
| "size"
|
|
20
|
+
| "radius"
|
|
21
|
+
| "color"
|
|
22
|
+
| "classNames"
|
|
23
|
+
| "className"
|
|
24
|
+
| "data"
|
|
25
|
+
> & {
|
|
26
|
+
className?: string;
|
|
27
|
+
classNames?: Partial<Record<string, string>>;
|
|
28
|
+
} & RecursicaSegmentedControlProps
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
function useSegmentedControlClassNames(restRecord: Record<string, unknown>): {
|
|
32
|
+
className: string;
|
|
33
|
+
classNames: Partial<Record<string, string>>;
|
|
34
|
+
} {
|
|
35
|
+
const mergedClassNames = mergeClassNames(
|
|
36
|
+
{
|
|
37
|
+
root: styles.root,
|
|
38
|
+
control: styles.control,
|
|
39
|
+
label: styles.label,
|
|
40
|
+
indicator: styles.indicator,
|
|
41
|
+
},
|
|
42
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
46
|
+
const finalClass = classNameProp
|
|
47
|
+
? `${styles.root} ${classNameProp}`
|
|
48
|
+
: styles.root;
|
|
49
|
+
|
|
50
|
+
return { className: finalClass, classNames: mergedClassNames };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
54
|
+
function SegmentedControl(
|
|
55
|
+
{
|
|
56
|
+
overStyled = false,
|
|
57
|
+
orientation = "horizontal",
|
|
58
|
+
fullWidth,
|
|
59
|
+
data = [],
|
|
60
|
+
...rest
|
|
61
|
+
},
|
|
62
|
+
ref,
|
|
63
|
+
) {
|
|
64
|
+
const sanitizedProps = filterStylingProps(rest, overStyled) as Partial<
|
|
65
|
+
typeof rest
|
|
66
|
+
>;
|
|
67
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
68
|
+
|
|
69
|
+
const stylingParams = useSegmentedControlClassNames(restRecord);
|
|
70
|
+
|
|
71
|
+
// Mantine's own data item has no icon slot; compose one into `label` (already a ReactNode)
|
|
72
|
+
// so Mantine's native innerLabel wrapper lays it out using the icon-size/gap tokens already
|
|
73
|
+
// wired in SegmentedControl.module.css.
|
|
74
|
+
const mappedData = data.map((item) =>
|
|
75
|
+
typeof item === "string" || !item.icon
|
|
76
|
+
? item
|
|
77
|
+
: {
|
|
78
|
+
...item,
|
|
79
|
+
label: (
|
|
80
|
+
<>
|
|
81
|
+
{item.icon}
|
|
82
|
+
{item.label}
|
|
83
|
+
</>
|
|
84
|
+
),
|
|
85
|
+
},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<MantineSegmentedControl
|
|
90
|
+
ref={ref}
|
|
91
|
+
{...(sanitizedProps as Omit<
|
|
92
|
+
MantineSegmentedControlProps,
|
|
93
|
+
"variant" | "size"
|
|
94
|
+
>)}
|
|
95
|
+
className={stylingParams.className}
|
|
96
|
+
classNames={stylingParams.classNames}
|
|
97
|
+
orientation={orientation}
|
|
98
|
+
fullWidth={fullWidth}
|
|
99
|
+
data-orientation={orientation}
|
|
100
|
+
data={mappedData}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
);
|
|
105
|
+
_SegmentedControl.displayName = "SegmentedControl";
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Recursica SegmentedControl component wrapping Mantine's SegmentedControl.
|
|
109
|
+
*/
|
|
110
|
+
export const SegmentedControl = _SegmentedControl;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# SegmentedControl - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `SegmentedControl` component in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { SegmentedControl } from "@recursica/adapter-mantine-v8";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { SegmentedControl } from "@recursica/adapter-mantine-v8";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return <SegmentedControl data={["Preview", "Code", "Edit"]} />;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Each `data` item may also be an object with an optional `icon`, rendered ahead of the label:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<SegmentedControl
|
|
30
|
+
data={[
|
|
31
|
+
{ value: "daily", label: "Daily", icon: <CheckIcon /> },
|
|
32
|
+
{ value: "weekly", label: "Weekly" },
|
|
33
|
+
]}
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 3. Design System Integration
|
|
40
|
+
|
|
41
|
+
All Recursica components in the `@recursica/adapter-mantine-v8` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
42
|
+
|
|
43
|
+
> [!IMPORTANT]
|
|
44
|
+
>
|
|
45
|
+
> - **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.
|
|
46
|
+
> - **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.
|
|
47
|
+
> - **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.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 4. Key Integration Features & Constraints
|
|
52
|
+
|
|
53
|
+
The `variant`, `size`, `radius`, and `color` props are not available on this component, since appearance is fully controlled by the design system tokens. The active segment is shown as a floating indicator that moves behind the selected label, with a divider rendered between adjacent segments.
|
|
54
|
+
|
|
55
|
+
A top-level `disabled` disables every item at once; an individual item can still be disabled on its own via `data[].disabled`.
|