@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,336 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { AutoComplete } from "./AutoComplete";
|
|
3
|
+
import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
|
|
4
|
+
import { renderRichOption } from "../../utils/renderRichOption";
|
|
5
|
+
import styles from "./AutoComplete.module.css";
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof AutoComplete> = {
|
|
8
|
+
title: "UI-Kit/AutoComplete",
|
|
9
|
+
component: AutoComplete,
|
|
10
|
+
tags: ["autodocs"],
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component: `
|
|
15
|
+
The \`AutoComplete\` primitive provides a text input with a dropdown menu for displaying suggestions as the user types.
|
|
16
|
+
|
|
17
|
+
### Architectural Decoupling
|
|
18
|
+
Recursica wraps the internal Mantine \`<Autocomplete>\` component inside the \`WithReadOnlyWrapper\`, ensuring it integrates perfectly with the strict design system form architecture.
|
|
19
|
+
|
|
20
|
+
### Examples
|
|
21
|
+
Always structure horizontal architectures via the generic \`formLayout\` parameter.
|
|
22
|
+
\`\`\`tsx
|
|
23
|
+
<AutoComplete
|
|
24
|
+
label="Country"
|
|
25
|
+
assistiveText="Select your country of residence."
|
|
26
|
+
data={["United States", "Canada", "Mexico", "United Kingdom", "France"]}
|
|
27
|
+
formLayout="stacked"
|
|
28
|
+
/>
|
|
29
|
+
\`\`\`
|
|
30
|
+
`,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
argTypes: {
|
|
35
|
+
...formControlArgTypes,
|
|
36
|
+
disabled: {
|
|
37
|
+
control: "boolean",
|
|
38
|
+
description:
|
|
39
|
+
"Maps the formal disabled variable states structurally to the input core.",
|
|
40
|
+
},
|
|
41
|
+
error: {
|
|
42
|
+
control: "text",
|
|
43
|
+
description:
|
|
44
|
+
"Applies the strict error string boundary rendering invalid structures seamlessly.",
|
|
45
|
+
},
|
|
46
|
+
required: {
|
|
47
|
+
control: "boolean",
|
|
48
|
+
},
|
|
49
|
+
label: {
|
|
50
|
+
control: "text",
|
|
51
|
+
},
|
|
52
|
+
assistiveText: {
|
|
53
|
+
control: "text",
|
|
54
|
+
},
|
|
55
|
+
readOnly: {
|
|
56
|
+
control: "boolean",
|
|
57
|
+
description:
|
|
58
|
+
"Toggles structural read-only data presentation explicitly blocking standard component bindings.",
|
|
59
|
+
},
|
|
60
|
+
wrapItemText: {
|
|
61
|
+
control: "boolean",
|
|
62
|
+
description:
|
|
63
|
+
"Wraps option label/supportingText onto additional lines instead of truncating with an ellipsis.",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default meta;
|
|
69
|
+
|
|
70
|
+
type Story = StoryObj<typeof AutoComplete>;
|
|
71
|
+
|
|
72
|
+
export const Default: Story = {
|
|
73
|
+
args: {
|
|
74
|
+
disabled: false,
|
|
75
|
+
readOnly: false,
|
|
76
|
+
label: "Country Selection",
|
|
77
|
+
placeholder: "Start typing...",
|
|
78
|
+
data: [
|
|
79
|
+
"United States",
|
|
80
|
+
"Canada",
|
|
81
|
+
"Mexico",
|
|
82
|
+
"United Kingdom",
|
|
83
|
+
"France",
|
|
84
|
+
"Germany",
|
|
85
|
+
"Japan",
|
|
86
|
+
"Brazil",
|
|
87
|
+
"India",
|
|
88
|
+
"Australia",
|
|
89
|
+
],
|
|
90
|
+
assistiveText: "Search from a predefined list of countries.",
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const FormsSideBySide: Story = {
|
|
95
|
+
args: {
|
|
96
|
+
label: "Primary Region",
|
|
97
|
+
placeholder: "Select region...",
|
|
98
|
+
data: ["US-East", "US-West", "EU-Central", "AP-South", "SA-East"],
|
|
99
|
+
assistiveText:
|
|
100
|
+
"Select the primary region for the deployment. This violently long string tests native textual wrapping safely mapping alongside inputs.",
|
|
101
|
+
formLayout: "side-by-side",
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const WithLeadingIcon: Story = {
|
|
106
|
+
args: {
|
|
107
|
+
label: "Search Projects",
|
|
108
|
+
placeholder: "Project name...",
|
|
109
|
+
data: ["Alpha", "Beta", "Gamma", "Delta", "Epsilon"],
|
|
110
|
+
leftSection: (
|
|
111
|
+
<svg
|
|
112
|
+
width="24"
|
|
113
|
+
height="24"
|
|
114
|
+
viewBox="0 0 24 24"
|
|
115
|
+
fill="none"
|
|
116
|
+
stroke="currentColor"
|
|
117
|
+
strokeWidth="2"
|
|
118
|
+
strokeLinecap="round"
|
|
119
|
+
strokeLinejoin="round"
|
|
120
|
+
>
|
|
121
|
+
<circle cx="11" cy="11" r="8"></circle>
|
|
122
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
123
|
+
</svg>
|
|
124
|
+
),
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const WithTrailingIcon: Story = {
|
|
129
|
+
args: {
|
|
130
|
+
label: "Validation URL",
|
|
131
|
+
placeholder: "https://recursica.dev",
|
|
132
|
+
data: [
|
|
133
|
+
"https://recursica.dev",
|
|
134
|
+
"https://beta.recursica.dev",
|
|
135
|
+
"https://api.recursica.dev",
|
|
136
|
+
],
|
|
137
|
+
rightSection: (
|
|
138
|
+
<svg
|
|
139
|
+
width="24"
|
|
140
|
+
height="24"
|
|
141
|
+
viewBox="0 0 24 24"
|
|
142
|
+
fill="none"
|
|
143
|
+
stroke="currentColor"
|
|
144
|
+
strokeWidth="2"
|
|
145
|
+
strokeLinecap="round"
|
|
146
|
+
strokeLinejoin="round"
|
|
147
|
+
>
|
|
148
|
+
<polyline points="20 6 9 17 4 12"></polyline>
|
|
149
|
+
</svg>
|
|
150
|
+
),
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const UserIcon = (
|
|
155
|
+
<svg
|
|
156
|
+
width="16"
|
|
157
|
+
height="16"
|
|
158
|
+
viewBox="0 0 24 24"
|
|
159
|
+
fill="none"
|
|
160
|
+
stroke="currentColor"
|
|
161
|
+
strokeWidth="2"
|
|
162
|
+
strokeLinecap="round"
|
|
163
|
+
strokeLinejoin="round"
|
|
164
|
+
>
|
|
165
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
|
166
|
+
<circle cx="12" cy="7" r="4"></circle>
|
|
167
|
+
</svg>
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
export const WithRichOptions: Story = {
|
|
171
|
+
args: {
|
|
172
|
+
label: "Assignee",
|
|
173
|
+
placeholder: "Search team members...",
|
|
174
|
+
data: [
|
|
175
|
+
{
|
|
176
|
+
value: "jdoe",
|
|
177
|
+
label: "Jane Doe",
|
|
178
|
+
leadingIcon: UserIcon,
|
|
179
|
+
supportingText: "jane.doe@example.com",
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
value: "asmith",
|
|
183
|
+
label: "Alex Smith",
|
|
184
|
+
leadingIcon: UserIcon,
|
|
185
|
+
supportingText: "alex.smith@example.com",
|
|
186
|
+
},
|
|
187
|
+
{ value: "unassigned", label: "Unassigned" },
|
|
188
|
+
],
|
|
189
|
+
assistiveText:
|
|
190
|
+
"Each option can show a leading icon and supporting text — see MANTINE_ADAPTER_RICH_OPTION_DATA.md.",
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const WithRichOptionsWrapped: Story = {
|
|
195
|
+
args: {
|
|
196
|
+
label: "Assignee",
|
|
197
|
+
placeholder: "Search team members...",
|
|
198
|
+
wrapItemText: true,
|
|
199
|
+
data: [
|
|
200
|
+
{
|
|
201
|
+
value: "jdoe",
|
|
202
|
+
label: "Jane Doe, Senior Staff Engineer, Platform Infrastructure",
|
|
203
|
+
leadingIcon: UserIcon,
|
|
204
|
+
supportingText:
|
|
205
|
+
"jane.doe@example.com — Platform Infrastructure team, on-call rotation lead",
|
|
206
|
+
},
|
|
207
|
+
{ value: "unassigned", label: "Unassigned" },
|
|
208
|
+
],
|
|
209
|
+
assistiveText:
|
|
210
|
+
"wrapItemText=true — long label/supportingText wrap instead of truncating.",
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const optionRowPreviewClassNames = {
|
|
215
|
+
optionContent: styles.optionContent,
|
|
216
|
+
optionIcon: styles.optionIcon,
|
|
217
|
+
optionText: styles.optionText,
|
|
218
|
+
optionTextWrap: styles.optionTextWrap,
|
|
219
|
+
optionSupportingText: styles.optionSupportingText,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const OPTION_ROW_PREVIEW_ITEMS = [
|
|
223
|
+
{
|
|
224
|
+
value: "icon-and-supporting",
|
|
225
|
+
label: "Jane Doe",
|
|
226
|
+
leadingIcon: UserIcon,
|
|
227
|
+
supportingText: "jane.doe@example.com",
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
value: "no-icon",
|
|
231
|
+
label: "Alex Smith",
|
|
232
|
+
supportingText:
|
|
233
|
+
"No leadingIcon — label/supportingText shift left, no reserved icon space",
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
value: "no-supporting-text",
|
|
237
|
+
label: "Taylor Rivera",
|
|
238
|
+
leadingIcon: UserIcon,
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
value: "plain",
|
|
242
|
+
label: "Plain option — no leadingIcon, no supportingText",
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
value: "long-text",
|
|
246
|
+
label:
|
|
247
|
+
"A very long option label that, with wrapItemText, wraps onto a second line instead of overflowing the fixed-width dropdown — otherwise it truncates with an ellipsis",
|
|
248
|
+
leadingIcon: UserIcon,
|
|
249
|
+
supportingText:
|
|
250
|
+
"A similarly long supporting text string, to confirm the same wrap-or-truncate behavior applies to it too",
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
// Renders the option row content directly — outside the floating/portal menu — inside a
|
|
255
|
+
// container sized to AutoComplete's own max-width token. Spacing between rows, icon/
|
|
256
|
+
// supportingText presence-or-absence alignment, and long-text wrapping/truncation are all much
|
|
257
|
+
// easier to inspect this way than by opening the real (portal-rendered) combobox dropdown. See
|
|
258
|
+
// MANTINE_ADAPTER_RICH_OPTION_DATA.md.
|
|
259
|
+
const renderOptionRowPreview = (wrapItemText: boolean) => (
|
|
260
|
+
<div
|
|
261
|
+
className={styles.dropdown}
|
|
262
|
+
style={{
|
|
263
|
+
width:
|
|
264
|
+
"var(--recursica_ui-kit_components_autocomplete_variants_layouts_stacked_properties_max-width)",
|
|
265
|
+
}}
|
|
266
|
+
>
|
|
267
|
+
{OPTION_ROW_PREVIEW_ITEMS.map((item) => (
|
|
268
|
+
<div key={item.value} className={styles.option}>
|
|
269
|
+
{renderRichOption(
|
|
270
|
+
{ option: item },
|
|
271
|
+
optionRowPreviewClassNames,
|
|
272
|
+
wrapItemText,
|
|
273
|
+
)}
|
|
274
|
+
</div>
|
|
275
|
+
))}
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
// Default: `wrapItemText` is false — label/supportingText truncate to a single line with an
|
|
280
|
+
// ellipsis instead of wrapping.
|
|
281
|
+
export const RichOptionRowPreview: Story = {
|
|
282
|
+
parameters: {
|
|
283
|
+
controls: { disable: true },
|
|
284
|
+
},
|
|
285
|
+
render: () => renderOptionRowPreview(false),
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// `wrapItemText: true` — label/supportingText wrap onto additional lines instead of truncating.
|
|
289
|
+
export const RichOptionRowPreviewWrapped: Story = {
|
|
290
|
+
parameters: {
|
|
291
|
+
controls: { disable: true },
|
|
292
|
+
},
|
|
293
|
+
render: () => renderOptionRowPreview(true),
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
export const Disabled: Story = {
|
|
297
|
+
args: {
|
|
298
|
+
label: "Disabled Deployment Node",
|
|
299
|
+
placeholder: "Disabled primitive map...",
|
|
300
|
+
data: ["Node 1", "Node 2", "Node 3"],
|
|
301
|
+
disabled: true,
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
export const ErrorState: Story = {
|
|
306
|
+
args: {
|
|
307
|
+
label: "Cluster Failure",
|
|
308
|
+
placeholder: "Failing component instance...",
|
|
309
|
+
data: ["Cluster A", "Cluster B", "Cluster C"],
|
|
310
|
+
defaultValue: "Invalid Cluster",
|
|
311
|
+
error:
|
|
312
|
+
"Critical runtime node disconnect detected traversing DOM architecture.",
|
|
313
|
+
required: true,
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export const StaticReadOnly: Story = {
|
|
318
|
+
args: {
|
|
319
|
+
label: "Static ReadOnly Review",
|
|
320
|
+
placeholder: "Ignored...",
|
|
321
|
+
data: ["Option 1", "Option 2"],
|
|
322
|
+
value: "Explicitly Uneditable Bound Output",
|
|
323
|
+
readOnly: true,
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
export const EditableReadOnly: Story = {
|
|
328
|
+
args: {
|
|
329
|
+
label: "Editable ReadOnly Review",
|
|
330
|
+
placeholder: "Ignored until active...",
|
|
331
|
+
data: ["Option 1", "Option 2"],
|
|
332
|
+
defaultValue: "Waiting for Edit Execution",
|
|
333
|
+
readOnly: true,
|
|
334
|
+
labelWithEditIcon: true,
|
|
335
|
+
},
|
|
336
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future AutoComplete component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Autocomplete as MantineAutocomplete,
|
|
4
|
+
type AutocompleteProps as MantineAutocompleteProps,
|
|
5
|
+
type InputWrapperProps,
|
|
6
|
+
} from "@mantine/core";
|
|
7
|
+
import {
|
|
8
|
+
type ReadOnlyControlProps,
|
|
9
|
+
normalizeComboboxData,
|
|
10
|
+
} from "@recursica/adapter-common";
|
|
11
|
+
import {
|
|
12
|
+
filterStylingProps,
|
|
13
|
+
omitUnsupportedProps,
|
|
14
|
+
mergeClassNames,
|
|
15
|
+
type RecursicaOverStyled,
|
|
16
|
+
} from "../../utils/filterStylingProps";
|
|
17
|
+
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
18
|
+
import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
|
|
19
|
+
import { renderRichOption } from "../../utils/renderRichOption";
|
|
20
|
+
import styles from "./AutoComplete.module.css";
|
|
21
|
+
|
|
22
|
+
import { type RecursicaAutocompleteProps as BaseRecursicaAutocompleteProps } from "@recursica/adapter-common";
|
|
23
|
+
|
|
24
|
+
export interface RecursicaAutoCompleteProps
|
|
25
|
+
extends Omit<
|
|
26
|
+
MantineAutocompleteProps,
|
|
27
|
+
| "size"
|
|
28
|
+
| "variant"
|
|
29
|
+
| "radius"
|
|
30
|
+
| "wrapperProps"
|
|
31
|
+
| "data"
|
|
32
|
+
| "defaultValue"
|
|
33
|
+
| "value"
|
|
34
|
+
>,
|
|
35
|
+
Pick<
|
|
36
|
+
InputWrapperProps,
|
|
37
|
+
"label" | "error" | "required" | "withAsterisk" | "id"
|
|
38
|
+
>,
|
|
39
|
+
Omit<
|
|
40
|
+
RecursicaFormControlWrapperProps,
|
|
41
|
+
"controlMaxWidth" | "controlMinWidth"
|
|
42
|
+
>,
|
|
43
|
+
ReadOnlyControlProps,
|
|
44
|
+
BaseRecursicaAutocompleteProps {
|
|
45
|
+
/** Current input value */
|
|
46
|
+
value?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type AutoCompleteProps = RecursicaOverStyled<RecursicaAutoCompleteProps>;
|
|
50
|
+
|
|
51
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
52
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
53
|
+
const UNSUPPORTED_PROPS = [
|
|
54
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
55
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
56
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
57
|
+
] as const satisfies readonly (keyof MantineAutocompleteProps)[];
|
|
58
|
+
|
|
59
|
+
export const AutoComplete = forwardRef<HTMLInputElement, AutoCompleteProps>(
|
|
60
|
+
function AutoComplete(props, ref) {
|
|
61
|
+
const {
|
|
62
|
+
overStyled = false,
|
|
63
|
+
formLayout = "stacked",
|
|
64
|
+
|
|
65
|
+
// Label & Wrapper Maps
|
|
66
|
+
labelSize,
|
|
67
|
+
labelAlignment,
|
|
68
|
+
labelOptionalText,
|
|
69
|
+
labelWithEditIcon,
|
|
70
|
+
onLabelEditClick,
|
|
71
|
+
|
|
72
|
+
label,
|
|
73
|
+
assistiveText,
|
|
74
|
+
assistiveWithIcon,
|
|
75
|
+
error,
|
|
76
|
+
required,
|
|
77
|
+
withAsterisk,
|
|
78
|
+
id,
|
|
79
|
+
className,
|
|
80
|
+
style,
|
|
81
|
+
disabled,
|
|
82
|
+
readOnly,
|
|
83
|
+
readOnlyComponent,
|
|
84
|
+
emptyValueComponent,
|
|
85
|
+
value,
|
|
86
|
+
defaultValue,
|
|
87
|
+
data,
|
|
88
|
+
renderOption,
|
|
89
|
+
wrapItemText = false,
|
|
90
|
+
...rest
|
|
91
|
+
} = props;
|
|
92
|
+
|
|
93
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
94
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
95
|
+
UNSUPPORTED_PROPS,
|
|
96
|
+
);
|
|
97
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
98
|
+
|
|
99
|
+
// Mantine's own data parser only preserves extra fields (`leadingIcon`/`supportingText`) when
|
|
100
|
+
// an item already has both `value` and `label` — an item with `value` only is rebuilt into a
|
|
101
|
+
// bare `{value, label: value, disabled}` object, silently dropping them (see
|
|
102
|
+
// get-parsed-combobox-data.mjs). `normalizeComboboxData` backfills `label` so the rich fields
|
|
103
|
+
// always survive regardless of whether the caller set it.
|
|
104
|
+
const normalizedData = normalizeComboboxData(data);
|
|
105
|
+
|
|
106
|
+
// Securely map core native blocks down ensuring nested CSS modules map precisely
|
|
107
|
+
const mergedClassNames = mergeClassNames(
|
|
108
|
+
{
|
|
109
|
+
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
110
|
+
input: styles.input,
|
|
111
|
+
section: styles.section,
|
|
112
|
+
dropdown: styles.dropdown,
|
|
113
|
+
option: styles.option,
|
|
114
|
+
},
|
|
115
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const optionClassNames = {
|
|
119
|
+
optionContent: styles.optionContent,
|
|
120
|
+
optionIcon: styles.optionIcon,
|
|
121
|
+
optionText: styles.optionText,
|
|
122
|
+
optionTextWrap: styles.optionTextWrap,
|
|
123
|
+
optionSupportingText: styles.optionSupportingText,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const wrapperClass = className
|
|
127
|
+
? `${styles.layoutOverride} ${className}`
|
|
128
|
+
: styles.layoutOverride;
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<WithReadOnlyWrapper
|
|
132
|
+
className={wrapperClass}
|
|
133
|
+
style={style as React.CSSProperties}
|
|
134
|
+
controlMaxWidth="var(--autocomplete-control-max-width)"
|
|
135
|
+
controlMinWidth="var(--autocomplete-control-min-width)"
|
|
136
|
+
overStyled={overStyled as true}
|
|
137
|
+
formLayout={formLayout}
|
|
138
|
+
labelSize={labelSize}
|
|
139
|
+
labelAlignment={labelAlignment}
|
|
140
|
+
labelOptionalText={labelOptionalText}
|
|
141
|
+
labelWithEditIcon={labelWithEditIcon}
|
|
142
|
+
onLabelEditClick={onLabelEditClick}
|
|
143
|
+
label={label}
|
|
144
|
+
assistiveText={assistiveText}
|
|
145
|
+
assistiveWithIcon={assistiveWithIcon}
|
|
146
|
+
error={error}
|
|
147
|
+
required={required}
|
|
148
|
+
withAsterisk={withAsterisk}
|
|
149
|
+
id={id}
|
|
150
|
+
readOnly={readOnly}
|
|
151
|
+
readOnlyComponent={readOnlyComponent}
|
|
152
|
+
emptyValueComponent={emptyValueComponent}
|
|
153
|
+
readOnlyType="text"
|
|
154
|
+
readOnlyValue={value !== undefined ? value : defaultValue}
|
|
155
|
+
readOnlyNativeProps={props}
|
|
156
|
+
activeComponent={
|
|
157
|
+
/* Naked Input execution safely decoupled from Mantine's macro Input.Wrapper DOM hooks */
|
|
158
|
+
<MantineAutocomplete
|
|
159
|
+
ref={ref}
|
|
160
|
+
{...(sanitizedProps as unknown as MantineAutocompleteProps)}
|
|
161
|
+
classNames={mergedClassNames}
|
|
162
|
+
disabled={disabled}
|
|
163
|
+
value={value as string | undefined}
|
|
164
|
+
defaultValue={defaultValue as string | undefined}
|
|
165
|
+
error={!!error}
|
|
166
|
+
data={normalizedData as unknown as MantineAutocompleteProps["data"]}
|
|
167
|
+
renderOption={
|
|
168
|
+
renderOption ??
|
|
169
|
+
((input) =>
|
|
170
|
+
renderRichOption(input, optionClassNames, wrapItemText))
|
|
171
|
+
}
|
|
172
|
+
/>
|
|
173
|
+
}
|
|
174
|
+
/>
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
AutoComplete.displayName = "AutoComplete";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# AutoComplete - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `AutoComplete` component in your projects using `@recursica/adapter-mantine-v8`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { AutoComplete } from "@recursica/adapter-mantine-v8";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { AutoComplete } from "@recursica/adapter-mantine-v8";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return (
|
|
23
|
+
<AutoComplete
|
|
24
|
+
label="Country"
|
|
25
|
+
placeholder="Type a country name..."
|
|
26
|
+
data={["USA", "Canada", "Mexico"]}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 3. Design System Integration
|
|
35
|
+
|
|
36
|
+
All Recursica components in the `@recursica/adapter-mantine-v8` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
37
|
+
|
|
38
|
+
> [!IMPORTANT]
|
|
39
|
+
>
|
|
40
|
+
> - **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.
|
|
41
|
+
> - **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.
|
|
42
|
+
> - **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.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 4. Key Integration Features & Constraints
|
|
47
|
+
|
|
48
|
+
### Rich option content: `leadingIcon` / `supportingText`
|
|
49
|
+
|
|
50
|
+
`data` items can carry an icon and a secondary line of text, rendered inside each option row:
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<AutoComplete
|
|
54
|
+
label="Assignee"
|
|
55
|
+
data={[
|
|
56
|
+
{
|
|
57
|
+
value: "jdoe",
|
|
58
|
+
label: "Jane Doe",
|
|
59
|
+
leadingIcon: <UserIcon />,
|
|
60
|
+
supportingText: "jane.doe@example.com",
|
|
61
|
+
},
|
|
62
|
+
{ value: "asmith", label: "Alex Smith" },
|
|
63
|
+
]}
|
|
64
|
+
/>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- `label` is optional, same as always — items with `value` only still work, falling back to
|
|
68
|
+
`value` as the displayed/matched text.
|
|
69
|
+
- Pass your own `renderOption` to opt out of this default rendering entirely for a given
|
|
70
|
+
component instance.
|
|
71
|
+
- By default `label`/`supportingText` truncate to a single line with an ellipsis. Set
|
|
72
|
+
`wrapItemText` to wrap them onto additional lines instead:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<AutoComplete data={data} wrapItemText />
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Known Limitation: Selected Option Highlight
|
|
79
|
+
|
|
80
|
+
Hover works (see `.option:hover`/`.option[data-hovered="true"]`), but there's no distinct "this option matches the current value" background — unlike `Dropdown`, which has one. This isn't a styling gap: Mantine's `Autocomplete` never passes a `value` prop into its internal `OptionsDropdown` (only `search`, for filtering — see `Autocomplete.mjs`), so `checked`/`data-combobox-active` (the attribute that drives `Dropdown`'s equivalent highlight) never gets set on any option, regardless of what's typed into the field. There's no other DOM signal to key a CSS rule off. Would need either an upstream Mantine change or reimplementing option rendering ourselves with a value comparison.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Avatar Component Implementation Notes
|
|
2
|
+
|
|
3
|
+
## Architecture Decisions
|
|
4
|
+
|
|
5
|
+
The `Avatar` component is an adapter over Mantine's `Avatar`. To ensure adherence to the `COMPONENT_GUIDE_WALKTHROUGH.md`:
|
|
6
|
+
|
|
7
|
+
- We do not wrap `MantineAvatar` in any custom standard `div` elements, preserving DOM structure.
|
|
8
|
+
- All styles strictly pull from explicit `--recursica_ui-kit_components_avatar_*` CSS tokens.
|
|
9
|
+
|
|
10
|
+
## Structural Workarounds
|
|
11
|
+
|
|
12
|
+
### Implicit `data-style`
|
|
13
|
+
|
|
14
|
+
Mantine's Avatar implicitly renders an image, an icon, or a text node based on the properties passed (`src`, `var`, `children`).
|
|
15
|
+
Recursica Tokens split Avatar styling distinctly across three separate categories: `image`, `icon`, and `text`.
|
|
16
|
+
To correctly map these variables, our React component observes standard prop states and manually injects a `data-style="image|icon|text"` onto the root. The `Avatar.module.css` explicitly gates padding and generic sizing modifiers under these `data-style` attributes.
|
|
17
|
+
|
|
18
|
+
### Flex Layout & Internal Spans
|
|
19
|
+
|
|
20
|
+
Since Avatar children (icons or initials) require robust centering that might differ heavily across Recursica size mappings, all child content defaults to being wrapped in `span` elements (either `.textWrapper` or `.iconWrapper`). These spans enforce 100% height and flex formatting independent of the Mantine container constraints.
|
|
21
|
+
|
|
22
|
+
### CSS Reset Hacks
|
|
23
|
+
|
|
24
|
+
Noticeable `/* HARDCODE: ... */` hacks are deployed within `.root` to completely zero-out Mantine's `--avatar-bg` and internal variables statically since Recursica handles background-colors inherently via the CSS variants cascade.
|
|
25
|
+
|
|
26
|
+
### `variant` mapping is a genuine match here (unlike MUI's)
|
|
27
|
+
|
|
28
|
+
Mantine's native `Avatar.variant` (`'filled'|'light'|'gradient'|'outline'|'transparent'|...`)
|
|
29
|
+
really is the same color-treatment concept Recursica's own `variant` is, so `mapVariant`
|
|
30
|
+
(`solid→filled, outline→outline, ghost→transparent`) is a correct, meaningful mapping — even
|
|
31
|
+
though the CSS reset hack above means it's visually inert either way. Worth noting only because
|
|
32
|
+
the MUI adapter's `Avatar.variant` means something completely different (shape) and had a real
|
|
33
|
+
bug from assuming the same word meant the same thing there; see mui-adapter's own
|
|
34
|
+
`AVATAR_IMPLEMENTATION_NOTES.md`.
|