@recursica/adapter-mui-v7 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 +582 -0
- package/LICENSE +21 -0
- package/OVERSTYLING.md +59 -0
- package/README.md +70 -0
- package/SETUP.md +92 -0
- package/USAGE.md +57 -0
- package/dist/adapter-mui-v7.cjs +292 -0
- package/dist/adapter-mui-v7.cjs.map +1 -0
- package/dist/adapter-mui-v7.css +1 -0
- package/dist/adapter-mui-v7.js +40757 -0
- package/dist/adapter-mui-v7.js.map +1 -0
- package/dist/index.d.ts +2350 -0
- package/dist/vite.svg +1 -0
- package/docs/PHILOSOPHY.md +39 -0
- package/llms.txt +76 -0
- package/package.json +151 -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 +184 -0
- package/src/OverStyling.tsx +87 -0
- package/src/Version.tsx +37 -0
- package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +107 -0
- package/src/components/Accordion/Accordion.module.css +362 -0
- package/src/components/Accordion/Accordion.stories.tsx +198 -0
- package/src/components/Accordion/Accordion.test.tsx +1 -0
- package/src/components/Accordion/Accordion.tsx +285 -0
- package/src/components/Accordion/USAGE.md +43 -0
- package/src/components/Accordion/index.ts +1 -0
- package/src/components/AssistiveElement/ASSISTIVEELEMENT_IMPLEMENTATION_NOTES.md +59 -0
- package/src/components/AssistiveElement/AssistiveElement.module.css +121 -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 +94 -0
- package/src/components/AssistiveElement/USAGE.md +36 -0
- package/src/components/AssistiveElement/index.ts +1 -0
- package/src/components/AutoComplete/AutoComplete.module.css +456 -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 +266 -0
- package/src/components/AutoComplete/IMPLEMENTATION_NOTES.md +37 -0
- package/src/components/AutoComplete/USAGE.md +68 -0
- package/src/components/AutoComplete/index.ts +1 -0
- package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +36 -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 +88 -0
- package/src/components/Avatar/USAGE.md +38 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Badge/Badge.module.css +115 -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 +61 -0
- package/src/components/Badge/USAGE.md +40 -0
- package/src/components/Badge/index.ts +1 -0
- package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +51 -0
- package/src/components/Breadcrumb/Breadcrumb.module.css +51 -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 +70 -0
- package/src/components/Breadcrumb/USAGE.md +42 -0
- package/src/components/Breadcrumb/index.ts +1 -0
- package/src/components/Button/BUTTON_IMPLEMENTATION_NOTES.md +123 -0
- package/src/components/Button/Button.module.css +413 -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 +156 -0
- package/src/components/Button/USAGE.md +46 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +15 -0
- package/src/components/Card/Card.module.css +155 -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 +202 -0
- package/src/components/Card/USAGE.md +57 -0
- package/src/components/Card/index.ts +1 -0
- package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +14 -0
- package/src/components/Checkbox/Checkbox.module.css +286 -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 +259 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +148 -0
- package/src/components/Checkbox/USAGE.md +36 -0
- package/src/components/Checkbox/index.ts +6 -0
- package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +102 -0
- package/src/components/Chip/Chip.module.css +283 -0
- package/src/components/Chip/Chip.stories.tsx +154 -0
- package/src/components/Chip/Chip.test.tsx +1 -0
- package/src/components/Chip/Chip.tsx +168 -0
- package/src/components/Chip/USAGE.md +55 -0
- package/src/components/Chip/index.ts +1 -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 +51 -0
- package/src/components/Container/IMPLEMENTATION_NOTES.md +5 -0
- package/src/components/Container/USAGE.md +48 -0
- package/src/components/Container/index.ts +1 -0
- package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +29 -0
- package/src/components/DatePicker/DatePicker.icons.tsx +35 -0
- package/src/components/DatePicker/DatePicker.module.css +464 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +163 -0
- package/src/components/DatePicker/DatePicker.test.tsx +1 -0
- package/src/components/DatePicker/DatePicker.tsx +229 -0
- package/src/components/DatePicker/USAGE.md +49 -0
- package/src/components/DatePicker/index.ts +1 -0
- package/src/components/Dropdown/BareDropdown.tsx +168 -0
- package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +45 -0
- package/src/components/Dropdown/Dropdown.icons.tsx +33 -0
- package/src/components/Dropdown/Dropdown.module.css +535 -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 +319 -0
- package/src/components/Dropdown/USAGE.md +68 -0
- package/src/components/Dropdown/index.ts +1 -0
- package/src/components/FileInput/FILEINPUT_IMPLEMENTATION_NOTES.md +153 -0
- package/src/components/FileInput/FileInput.module.css +268 -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 +415 -0
- package/src/components/FileInput/USAGE.md +145 -0
- package/src/components/FileInput/index.ts +1 -0
- package/src/components/FileUpload/FILEUPLOAD_IMPLEMENTATION_NOTES.md +249 -0
- package/src/components/FileUpload/FileUpload.module.css +200 -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 +352 -0
- package/src/components/FileUpload/USAGE.md +199 -0
- package/src/components/FileUpload/index.ts +1 -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 +89 -0
- package/src/components/Flex/USAGE.md +41 -0
- package/src/components/Flex/index.ts +1 -0
- package/src/components/FormControlLayout/FormControlLayout.module.css +92 -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 +72 -0
- package/src/components/FormControlLayout/USAGE.md +40 -0
- package/src/components/FormControlLayout/index.ts +1 -0
- package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +35 -0
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +87 -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 +149 -0
- package/src/components/FormControlWrapper/USAGE.md +40 -0
- package/src/components/FormControlWrapper/index.ts +1 -0
- package/src/components/Grid/Grid.module.css +72 -0
- package/src/components/Grid/Grid.stories.tsx +161 -0
- package/src/components/Grid/Grid.test.tsx +1 -0
- package/src/components/Grid/Grid.tsx +155 -0
- package/src/components/Grid/IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/Grid/USAGE.md +53 -0
- package/src/components/Grid/index.ts +1 -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 +116 -0
- package/src/components/Group/USAGE.md +41 -0
- package/src/components/Group/index.ts +1 -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 +28 -0
- package/src/components/Heading/USAGE.md +36 -0
- package/src/components/Heading/index.ts +1 -0
- package/src/components/HoverCard/HoverCard.module.css +107 -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 +145 -0
- package/src/components/HoverCard/USAGE.md +45 -0
- package/src/components/HoverCard/index.ts +1 -0
- package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +27 -0
- package/src/components/Label/Label.module.css +169 -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 +96 -0
- package/src/components/Label/USAGE.md +36 -0
- package/src/components/Label/index.ts +1 -0
- package/src/components/Layer/USAGE.md +50 -0
- package/src/components/Link/LINK_IMPLEMENTATION_NOTES.md +9 -0
- package/src/components/Link/Link.module.css +105 -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 +45 -0
- package/src/components/Link/USAGE.md +40 -0
- package/src/components/Link/index.ts +1 -0
- package/src/components/Loader/LOADER_IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/Loader/Loader.animate.dom.test.tsx +72 -0
- package/src/components/Loader/Loader.module.css +175 -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 +72 -0
- package/src/components/Loader/USAGE.md +42 -0
- package/src/components/Loader/index.ts +1 -0
- package/src/components/Menu/IMPLEMENTATION_NOTES.md +5 -0
- package/src/components/Menu/Menu.module.css +283 -0
- package/src/components/Menu/Menu.stories.tsx +405 -0
- package/src/components/Menu/Menu.test.tsx +1 -0
- package/src/components/Menu/Menu.tsx +103 -0
- package/src/components/Menu/USAGE.md +53 -0
- package/src/components/Menu/index.ts +1 -0
- package/src/components/Modal/MODAL_IMPLEMENTATION_NOTES.md +31 -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 +231 -0
- package/src/components/Modal/USAGE.md +40 -0
- package/src/components/Modal/index.ts +1 -0
- package/src/components/NumberInput/NUMBER_INPUT_IMPLEMENTATION_NOTES.md +93 -0
- package/src/components/NumberInput/NumberInput.module.css +303 -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 +273 -0
- package/src/components/NumberInput/USAGE.md +36 -0
- package/src/components/NumberInput/index.ts +1 -0
- package/src/components/Pagination/IMPLEMENTATION_NOTES.md +40 -0
- package/src/components/Pagination/Pagination.icons.tsx +66 -0
- package/src/components/Pagination/Pagination.module.css +197 -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 +123 -0
- package/src/components/Pagination/USAGE.md +36 -0
- package/src/components/Pagination/index.ts +1 -0
- package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +133 -0
- package/src/components/Panel/Panel.module.css +231 -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 +186 -0
- package/src/components/Panel/USAGE.md +46 -0
- package/src/components/Panel/index.ts +1 -0
- package/src/components/Popover/IMPLEMENTATION_NOTES.md +22 -0
- package/src/components/Popover/Popover.module.css +118 -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 +267 -0
- package/src/components/Popover/USAGE.md +69 -0
- package/src/components/Popover/index.ts +1 -0
- package/src/components/Radio/RADIO_IMPLEMENTATION_NOTES.md +12 -0
- package/src/components/Radio/Radio.module.css +247 -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 +223 -0
- package/src/components/Radio/RadioGroup.stories.tsx +117 -0
- package/src/components/Radio/RadioGroup.tsx +122 -0
- package/src/components/Radio/USAGE.md +36 -0
- package/src/components/Radio/index.ts +2 -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 +108 -0
- package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
- package/src/components/ReadOnlyField/USAGE.md +36 -0
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
- package/src/components/ReadOnlyField/index.ts +2 -0
- package/src/components/RecursicaThemeProvider/USAGE.md +60 -0
- package/src/components/SegmentedControl/IMPLEMENTATION_NOTES.md +14 -0
- package/src/components/SegmentedControl/SegmentedControl.module.css +201 -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 +149 -0
- package/src/components/SegmentedControl/USAGE.md +49 -0
- package/src/components/SegmentedControl/index.ts +1 -0
- package/src/components/Slider/IMPLEMENTATION_NOTES.md +55 -0
- package/src/components/Slider/Slider.module.css +635 -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 +435 -0
- package/src/components/Slider/USAGE.md +56 -0
- package/src/components/Slider/index.ts +1 -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 +43 -0
- package/src/components/Stack/USAGE.md +41 -0
- package/src/components/Stack/index.ts +1 -0
- package/src/components/Stepper/IMPLEMENTATION_NOTES.md +120 -0
- package/src/components/Stepper/Stepper.module.css +474 -0
- package/src/components/Stepper/Stepper.stories.tsx +157 -0
- package/src/components/Stepper/Stepper.test.tsx +1 -0
- package/src/components/Stepper/Stepper.tsx +240 -0
- package/src/components/Stepper/USAGE.md +45 -0
- package/src/components/Stepper/index.ts +1 -0
- package/src/components/Switch/SWITCH_IMPLEMENTATION_NOTES.md +147 -0
- package/src/components/Switch/Switch.module.css +346 -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 +294 -0
- package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
- package/src/components/Switch/SwitchGroup.tsx +156 -0
- package/src/components/Switch/USAGE.md +36 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/TABLE_IMPLEMENTATION_NOTES.md +75 -0
- package/src/components/Table/Table.module.css +462 -0
- package/src/components/Table/Table.stories.tsx +154 -0
- package/src/components/Table/Table.test.tsx +1 -0
- package/src/components/Table/Table.tsx +250 -0
- package/src/components/Table/USAGE.md +90 -0
- package/src/components/Table/index.ts +1 -0
- package/src/components/Tabs/IMPLEMENTATION_NOTES.md +76 -0
- package/src/components/Tabs/Tabs.module.css +801 -0
- package/src/components/Tabs/Tabs.stories.tsx +174 -0
- package/src/components/Tabs/Tabs.test.tsx +1 -0
- package/src/components/Tabs/Tabs.tsx +103 -0
- package/src/components/Tabs/USAGE.md +61 -0
- package/src/components/Tabs/index.ts +1 -0
- package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +10 -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 +19 -0
- package/src/components/Text/USAGE.md +40 -0
- package/src/components/Text/index.ts +1 -0
- package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +42 -0
- package/src/components/TextArea/TextArea.module.css +203 -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 +162 -0
- package/src/components/TextArea/USAGE.md +38 -0
- package/src/components/TextArea/index.ts +1 -0
- package/src/components/TextField/TextField.module.css +271 -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 +182 -0
- package/src/components/TextField/USAGE.md +38 -0
- package/src/components/TextField/index.ts +1 -0
- package/src/components/TimePicker/TIMEPICKER_IMPLEMENTATION_NOTES.md +89 -0
- package/src/components/TimePicker/TimePicker.module.css +262 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +155 -0
- package/src/components/TimePicker/TimePicker.test.tsx +1 -0
- package/src/components/TimePicker/TimePicker.tsx +277 -0
- package/src/components/TimePicker/USAGE.md +61 -0
- package/src/components/TimePicker/index.ts +1 -0
- package/src/components/Timeline/IMPLEMENTATION_NOTES.md +42 -0
- package/src/components/Timeline/Timeline.module.css +363 -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 +90 -0
- package/src/components/Timeline/TimelineItem.tsx +95 -0
- package/src/components/Timeline/USAGE.md +41 -0
- package/src/components/Timeline/index.ts +2 -0
- package/src/components/Toast/TOAST_IMPLEMENTATION_NOTES.md +37 -0
- package/src/components/Toast/Toast.module.css +193 -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 +121 -0
- package/src/components/Toast/USAGE.md +42 -0
- package/src/components/Toast/index.ts +1 -0
- package/src/components/Tooltip/Tooltip.module.css +83 -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 +78 -0
- package/src/components/Tooltip/USAGE.md +40 -0
- package/src/components/Tooltip/index.ts +1 -0
- package/src/components/TransferList/TRANSFERLIST_IMPLEMENTATION_NOTES.md +140 -0
- package/src/components/TransferList/TransferList.module.css +174 -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/TransferList/index.ts +1 -0
- package/src/components/Tree/IMPLEMENTATION_NOTES.md +53 -0
- package/src/components/Tree/Tree.module.css +272 -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 +298 -0
- package/src/components/Tree/USAGE.md +99 -0
- package/src/components/Tree/index.ts +1 -0
- package/src/components/Typography/TYPOGRAPHY_IMPLEMENTATION_NOTES.md +17 -0
- package/src/components/Typography/Typography.module.css +13 -0
- package/src/components/Typography/Typography.test.tsx +1 -0
- package/src/components/Typography/Typography.tsx +43 -0
- package/src/components/Typography/USAGE.md +40 -0
- package/src/components/Typography/index.ts +1 -0
- package/src/components/index.ts +50 -0
- package/src/env.d.ts +7 -0
- package/src/index.ts +194 -0
- package/src/types/index.ts +9 -0
- package/src/types/scss-modules.d.ts +9 -0
- package/src/utils/ColorSchemeWrapper.tsx +23 -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 +143 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/renderRichOption.tsx +51 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { NumberInput } from "./NumberInput";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof NumberInput> = {
|
|
5
|
+
title: "UI-Kit/NumberInput",
|
|
6
|
+
component: NumberInput,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
argTypes: {
|
|
9
|
+
label: { control: "text" },
|
|
10
|
+
assistiveText: { control: "text" },
|
|
11
|
+
disabled: { control: "boolean" },
|
|
12
|
+
error: { control: "boolean" },
|
|
13
|
+
readOnly: { control: "boolean" },
|
|
14
|
+
required: { control: "boolean" },
|
|
15
|
+
hideControls: { control: "boolean" },
|
|
16
|
+
formLayout: {
|
|
17
|
+
control: "select",
|
|
18
|
+
options: ["stacked", "side-by-side"],
|
|
19
|
+
},
|
|
20
|
+
labelSize: {
|
|
21
|
+
control: "select",
|
|
22
|
+
options: ["small", "default", "large"],
|
|
23
|
+
},
|
|
24
|
+
assistiveWithIcon: { table: { disable: true } },
|
|
25
|
+
labelOptionalText: { table: { disable: true } },
|
|
26
|
+
labelWithEditIcon: { table: { disable: true } },
|
|
27
|
+
onLabelEditClick: { table: { disable: true } },
|
|
28
|
+
emptyValueComponent: { table: { disable: true } },
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default meta;
|
|
33
|
+
|
|
34
|
+
type Story = StoryObj<typeof NumberInput>;
|
|
35
|
+
|
|
36
|
+
export const Default: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
label: "Amount",
|
|
39
|
+
placeholder: "Enter an amount",
|
|
40
|
+
assistiveText: "Must be greater than 0",
|
|
41
|
+
defaultValue: 10,
|
|
42
|
+
min: 0,
|
|
43
|
+
max: 100,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const SideBySideLayout: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
...Default.args,
|
|
50
|
+
formLayout: "side-by-side",
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const States: Story = {
|
|
55
|
+
render: () => (
|
|
56
|
+
<div
|
|
57
|
+
style={{
|
|
58
|
+
display: "flex",
|
|
59
|
+
flexDirection: "column",
|
|
60
|
+
gap: "1rem",
|
|
61
|
+
maxWidth: 400,
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
64
|
+
<NumberInput label="Default" placeholder="Enter a number" />
|
|
65
|
+
<NumberInput label="Disabled" placeholder="Disabled input" disabled />
|
|
66
|
+
<NumberInput label="Error" placeholder="Error state" error />
|
|
67
|
+
<NumberInput label="Read Only" value={42} readOnly />
|
|
68
|
+
<NumberInput label="Required" required />
|
|
69
|
+
</div>
|
|
70
|
+
),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const WithLeftIcon: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
label: "Price",
|
|
76
|
+
placeholder: "0.00",
|
|
77
|
+
leftSection: <span>$</span>,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const WithRightIcon: Story = {
|
|
82
|
+
args: {
|
|
83
|
+
label: "Percentage",
|
|
84
|
+
placeholder: "0",
|
|
85
|
+
rightSection: <span>%</span>,
|
|
86
|
+
hideControls: true, // Typically hiding controls if rightSection is occupied
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const HiddenControls: Story = {
|
|
91
|
+
args: {
|
|
92
|
+
label: "Zip Code",
|
|
93
|
+
placeholder: "Enter zip code",
|
|
94
|
+
hideControls: true,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future NumberInput component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback } from "react";
|
|
2
|
+
import { InputBase, type InputBaseProps } from "@mui/material";
|
|
3
|
+
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
4
|
+
import {
|
|
5
|
+
filterStylingProps,
|
|
6
|
+
omitUnsupportedProps,
|
|
7
|
+
mergeClassNames,
|
|
8
|
+
type RecursicaOverStyled,
|
|
9
|
+
} from "../../utils/filterStylingProps";
|
|
10
|
+
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
11
|
+
import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
|
|
12
|
+
import styles from "./NumberInput.module.css";
|
|
13
|
+
|
|
14
|
+
import { type RecursicaNumberInputProps as BaseRecursicaNumberInputProps } from "@recursica/adapter-common";
|
|
15
|
+
|
|
16
|
+
export interface RecursicaNumberInputProps
|
|
17
|
+
extends Omit<
|
|
18
|
+
InputBaseProps,
|
|
19
|
+
| "color"
|
|
20
|
+
| "size"
|
|
21
|
+
| "startAdornment"
|
|
22
|
+
| "endAdornment"
|
|
23
|
+
| "autoComplete"
|
|
24
|
+
| "error"
|
|
25
|
+
>,
|
|
26
|
+
Pick<
|
|
27
|
+
RecursicaFormControlWrapperProps,
|
|
28
|
+
| "label"
|
|
29
|
+
| "error"
|
|
30
|
+
| "required"
|
|
31
|
+
| "id"
|
|
32
|
+
| "assistiveText"
|
|
33
|
+
| "assistiveWithIcon"
|
|
34
|
+
| "formLayout"
|
|
35
|
+
| "labelSize"
|
|
36
|
+
| "labelAlignment"
|
|
37
|
+
| "labelOptionalText"
|
|
38
|
+
| "labelWithEditIcon"
|
|
39
|
+
| "onLabelEditClick"
|
|
40
|
+
>,
|
|
41
|
+
ReadOnlyControlProps,
|
|
42
|
+
BaseRecursicaNumberInputProps {}
|
|
43
|
+
|
|
44
|
+
export type NumberInputProps = RecursicaOverStyled<RecursicaNumberInputProps>;
|
|
45
|
+
|
|
46
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
47
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
48
|
+
const UNSUPPORTED_PROPS = [
|
|
49
|
+
"size", // Recursica controls sizing via design tokens, not MUI's native small/medium size
|
|
50
|
+
"color", // Colors are token-driven; MUI's native palette isn't exposed
|
|
51
|
+
] as const satisfies readonly (keyof InputBaseProps)[];
|
|
52
|
+
|
|
53
|
+
// Keys a plain, non-destructive keystroke always passes through (navigation, editing, shortcuts).
|
|
54
|
+
const NON_CHARACTER_KEYS = new Set([
|
|
55
|
+
"Backspace",
|
|
56
|
+
"Delete",
|
|
57
|
+
"Tab",
|
|
58
|
+
"Escape",
|
|
59
|
+
"Enter",
|
|
60
|
+
"ArrowLeft",
|
|
61
|
+
"ArrowRight",
|
|
62
|
+
"ArrowUp",
|
|
63
|
+
"ArrowDown",
|
|
64
|
+
"Home",
|
|
65
|
+
"End",
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Restricts keystrokes to what a numeric value can legally contain — digits, a single decimal
|
|
70
|
+
* point, and (when negative values are allowed) a single leading minus sign. Mirrors Mantine's
|
|
71
|
+
* `NumberInput`, which parses/rejects non-numeric characters internally; MUI's `InputBase` has
|
|
72
|
+
* no such behavior built in, so it has to be reimplemented here.
|
|
73
|
+
*/
|
|
74
|
+
function isAllowedNumericKeystroke(
|
|
75
|
+
event: React.KeyboardEvent<HTMLInputElement>,
|
|
76
|
+
allowNegative: boolean,
|
|
77
|
+
): boolean {
|
|
78
|
+
if (event.ctrlKey || event.metaKey || event.altKey) return true;
|
|
79
|
+
if (NON_CHARACTER_KEYS.has(event.key)) return true;
|
|
80
|
+
if (/^[0-9]$/.test(event.key)) return true;
|
|
81
|
+
|
|
82
|
+
const target = event.currentTarget;
|
|
83
|
+
if (event.key === "." && !target.value.includes(".")) return true;
|
|
84
|
+
if (
|
|
85
|
+
allowNegative &&
|
|
86
|
+
event.key === "-" &&
|
|
87
|
+
target.selectionStart === 0 &&
|
|
88
|
+
!target.value.includes("-")
|
|
89
|
+
) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
|
|
97
|
+
function NumberInput(props, ref) {
|
|
98
|
+
const {
|
|
99
|
+
overStyled = false,
|
|
100
|
+
formLayout = "stacked",
|
|
101
|
+
|
|
102
|
+
// Label & Wrapper Maps
|
|
103
|
+
labelSize,
|
|
104
|
+
labelAlignment,
|
|
105
|
+
labelOptionalText,
|
|
106
|
+
labelWithEditIcon,
|
|
107
|
+
onLabelEditClick,
|
|
108
|
+
|
|
109
|
+
label,
|
|
110
|
+
assistiveText,
|
|
111
|
+
assistiveWithIcon,
|
|
112
|
+
error,
|
|
113
|
+
required,
|
|
114
|
+
id,
|
|
115
|
+
className,
|
|
116
|
+
style,
|
|
117
|
+
disabled,
|
|
118
|
+
readOnly,
|
|
119
|
+
readOnlyComponent,
|
|
120
|
+
emptyValueComponent,
|
|
121
|
+
value,
|
|
122
|
+
defaultValue,
|
|
123
|
+
leftSection,
|
|
124
|
+
rightSection,
|
|
125
|
+
min,
|
|
126
|
+
max,
|
|
127
|
+
step,
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
129
|
+
hideControls = false,
|
|
130
|
+
...rest
|
|
131
|
+
} = props;
|
|
132
|
+
|
|
133
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
134
|
+
filterStylingProps(rest, overStyled),
|
|
135
|
+
UNSUPPORTED_PROPS,
|
|
136
|
+
);
|
|
137
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
138
|
+
|
|
139
|
+
// Securely map core native blocks down ensuring nested CSS modules map precisely. The
|
|
140
|
+
// caller-facing "root"/"input" slot names (MUI's own InputBase `classes` shape) are
|
|
141
|
+
// translated to this component's internal "wrapper"/"input" naming below.
|
|
142
|
+
const callerClasses = restRecord.classes as
|
|
143
|
+
| Partial<Record<string, string>>
|
|
144
|
+
| undefined;
|
|
145
|
+
const mergedClassNames = mergeClassNames(
|
|
146
|
+
{
|
|
147
|
+
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
148
|
+
input: styles.input,
|
|
149
|
+
section: styles.section,
|
|
150
|
+
controls: styles.controls,
|
|
151
|
+
control: styles.control,
|
|
152
|
+
},
|
|
153
|
+
callerClasses && {
|
|
154
|
+
wrapper: callerClasses.root,
|
|
155
|
+
input: callerClasses.input,
|
|
156
|
+
},
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
const wrapperClass = className
|
|
160
|
+
? `${styles.layoutOverride} ${className}`
|
|
161
|
+
: styles.layoutOverride;
|
|
162
|
+
|
|
163
|
+
const startAdornment = leftSection ? (
|
|
164
|
+
<div className={mergedClassNames.section} data-position="left">
|
|
165
|
+
{leftSection}
|
|
166
|
+
</div>
|
|
167
|
+
) : undefined;
|
|
168
|
+
|
|
169
|
+
const endAdornment = rightSection ? (
|
|
170
|
+
<div className={mergedClassNames.section} data-position="right">
|
|
171
|
+
{rightSection}
|
|
172
|
+
</div>
|
|
173
|
+
) : undefined;
|
|
174
|
+
|
|
175
|
+
// Mantine's NumberInput refuses a leading "-" once `min` rules out negative values; mirror
|
|
176
|
+
// that here since it also drives what a keystroke is allowed to produce.
|
|
177
|
+
const allowNegative = min === undefined || min < 0;
|
|
178
|
+
|
|
179
|
+
const handleKeyDown = useCallback(
|
|
180
|
+
(event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
181
|
+
if (!isAllowedNumericKeystroke(event, allowNegative)) {
|
|
182
|
+
event.preventDefault();
|
|
183
|
+
}
|
|
184
|
+
(
|
|
185
|
+
restRecord.onKeyDown as
|
|
186
|
+
| React.KeyboardEventHandler<HTMLInputElement>
|
|
187
|
+
| undefined
|
|
188
|
+
)?.(event);
|
|
189
|
+
},
|
|
190
|
+
[allowNegative, restRecord.onKeyDown],
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
const handlePaste = useCallback(
|
|
194
|
+
(event: React.ClipboardEvent<HTMLInputElement>) => {
|
|
195
|
+
const pasted = event.clipboardData.getData("text");
|
|
196
|
+
const pattern = allowNegative
|
|
197
|
+
? /^-?[0-9]*\.?[0-9]*$/
|
|
198
|
+
: /^[0-9]*\.?[0-9]*$/;
|
|
199
|
+
if (!pattern.test(pasted)) {
|
|
200
|
+
event.preventDefault();
|
|
201
|
+
}
|
|
202
|
+
(
|
|
203
|
+
restRecord.onPaste as
|
|
204
|
+
| React.ClipboardEventHandler<HTMLInputElement>
|
|
205
|
+
| undefined
|
|
206
|
+
)?.(event);
|
|
207
|
+
},
|
|
208
|
+
[allowNegative, restRecord.onPaste],
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<WithReadOnlyWrapper
|
|
213
|
+
className={wrapperClass}
|
|
214
|
+
style={style as React.CSSProperties}
|
|
215
|
+
controlMaxWidth="var(--number-input-control-max-width)"
|
|
216
|
+
controlMinWidth="var(--number-input-control-min-width)"
|
|
217
|
+
overStyled={overStyled as true}
|
|
218
|
+
formLayout={formLayout}
|
|
219
|
+
labelSize={labelSize}
|
|
220
|
+
labelAlignment={labelAlignment}
|
|
221
|
+
labelOptionalText={labelOptionalText}
|
|
222
|
+
labelWithEditIcon={labelWithEditIcon}
|
|
223
|
+
onLabelEditClick={onLabelEditClick}
|
|
224
|
+
label={label}
|
|
225
|
+
assistiveText={assistiveText}
|
|
226
|
+
assistiveWithIcon={assistiveWithIcon}
|
|
227
|
+
error={error}
|
|
228
|
+
required={required}
|
|
229
|
+
id={id}
|
|
230
|
+
readOnly={readOnly}
|
|
231
|
+
readOnlyComponent={readOnlyComponent}
|
|
232
|
+
emptyValueComponent={emptyValueComponent}
|
|
233
|
+
readOnlyType="text"
|
|
234
|
+
readOnlyValue={
|
|
235
|
+
value !== undefined ? value?.toString() : defaultValue?.toString()
|
|
236
|
+
}
|
|
237
|
+
readOnlyNativeProps={props}
|
|
238
|
+
activeComponent={
|
|
239
|
+
/* Naked Input execution safely decoupled from Mui's macro Input.Wrapper DOM hooks */
|
|
240
|
+
<InputBase
|
|
241
|
+
inputRef={ref}
|
|
242
|
+
{...(sanitizedProps as unknown as InputBaseProps)}
|
|
243
|
+
classes={{
|
|
244
|
+
root: mergedClassNames.wrapper,
|
|
245
|
+
input: mergedClassNames.input,
|
|
246
|
+
}}
|
|
247
|
+
disabled={disabled}
|
|
248
|
+
value={value}
|
|
249
|
+
defaultValue={defaultValue}
|
|
250
|
+
startAdornment={startAdornment}
|
|
251
|
+
endAdornment={endAdornment}
|
|
252
|
+
inputMode="decimal"
|
|
253
|
+
onKeyDown={handleKeyDown}
|
|
254
|
+
onPaste={handlePaste}
|
|
255
|
+
inputProps={{
|
|
256
|
+
min,
|
|
257
|
+
max,
|
|
258
|
+
step,
|
|
259
|
+
...(restRecord.inputProps as Record<string, unknown>),
|
|
260
|
+
}}
|
|
261
|
+
// Bind native CSS selectors for errors / adornments explicitly to the root boundary
|
|
262
|
+
data-disabled={disabled ? "true" : undefined}
|
|
263
|
+
data-error={error ? "true" : undefined}
|
|
264
|
+
data-with-left-section={leftSection ? "true" : undefined}
|
|
265
|
+
data-with-right-section={rightSection ? "true" : undefined}
|
|
266
|
+
/>
|
|
267
|
+
}
|
|
268
|
+
/>
|
|
269
|
+
);
|
|
270
|
+
},
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
NumberInput.displayName = "NumberInput";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# NumberInput - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `NumberInput` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { NumberInput } from "@recursica/adapter-mui-v7";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { NumberInput } from "@recursica/adapter-mui-v7";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return <NumberInput label="Quantity" min={1} max={10} defaultValue={1} />;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 3. Design System Integration
|
|
29
|
+
|
|
30
|
+
All Recursica components in the `@recursica/adapter-mui-v7` package adhere strictly to design system spacing, scaling, and behavior patterns.
|
|
31
|
+
|
|
32
|
+
> [!IMPORTANT]
|
|
33
|
+
>
|
|
34
|
+
> - **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.
|
|
35
|
+
> - **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.
|
|
36
|
+
> - **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.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./NumberInput";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Pagination Implementation Notes
|
|
2
|
+
|
|
3
|
+
- **Compositional API Dropped:** Mantine's original `Pagination` component relies heavily on dot-notation sub-components (`Pagination.Root`, `Pagination.Items`, `Pagination.Control`, etc.). MUI's `<Pagination>` is fundamentally monolithic. Following architectural review, we have decided to drop the dot-notation wrappers for `adapter-mui-v7` and rely strictly on MUI's monolithic API. Storybook and visual regression tests have been updated to reflect this divergence while retaining core property mapping compatibility.
|
|
4
|
+
|
|
5
|
+
## `renderItem` was never wired up (source-of-truth audit, 2026-08-30)
|
|
6
|
+
|
|
7
|
+
`Pagination.module.css` already had complete, correctly-tokenized rules for `.control` (the
|
|
8
|
+
circle/pill for every page/nav item), `.dots` (the ellipsis), `.iconWithLabel`, and `.baseIcon` —
|
|
9
|
+
and `Pagination.icons.tsx` already had `PaginationIcon` plus `NextWithLabel`/`PrevWithLabel`/
|
|
10
|
+
`FirstWithLabel`/`LastWithLabel` fully built. None of it was ever applied: `Pagination.tsx` only
|
|
11
|
+
mapped MUI `Pagination`'s top-level `classes` prop (`root`/`ul` — the _only_ two slots MUI's own
|
|
12
|
+
`Pagination` component exposes) and silently discarded the `withLabels` prop entirely. Every
|
|
13
|
+
page/nav button rendered as MUI's own completely unstyled default `PaginationItem` — explaining
|
|
14
|
+
the whole cluster of reported issues at once: undersized circles (no `.control` height/width),
|
|
15
|
+
grey selected state and missing outline (no `.control`/`[data-active]` colors), wrong font color,
|
|
16
|
+
default MUI arrow icons in the wrong color (no `PaginationIcon`), default ripple (MUI's
|
|
17
|
+
`PaginationItem` uses `ButtonBase` with ripple enabled by default), and no text labels ever
|
|
18
|
+
possible (`withLabels` was read and thrown away).
|
|
19
|
+
|
|
20
|
+
**Fix:** `Pagination.tsx` now passes a `renderItem` to `MuiPagination` that renders every item as
|
|
21
|
+
`<PaginationItem className={styles.control} data-active={item.selected} data-variant={isNavigation
|
|
22
|
+
? "text" : undefined} disableRipple slots={...} />` (ellipsis items get `styles.dots` instead).
|
|
23
|
+
`slots.first/last/next/previous` point at `PaginationIcon` (plain) or the `*WithLabel` components
|
|
24
|
+
(when `withLabels` is true) — both were already correctly built to work as MUI `PaginationItem`
|
|
25
|
+
icon slots (only the icon itself receives MUI's forwarded className/props via `{...props}` spread
|
|
26
|
+
onto the inner `PaginationIcon`, not the outer label-wrapping `<div>`, so the label text isn't
|
|
27
|
+
constrained by MUI's icon-sized styled wrapper).
|
|
28
|
+
|
|
29
|
+
Also added a local `--pagination-control-size` bridge variable (bound to the Button height token
|
|
30
|
+
`.control` is already sized from) — `.baseIcon`'s `calc(var(--pagination-control-size) / 1.8)`
|
|
31
|
+
was copied verbatim from mantine-adapter, where `--pagination-control-size` is a _native_ Mantine
|
|
32
|
+
CSS variable Mantine's own `Pagination` stamps onto the DOM already; MUI has no equivalent, so
|
|
33
|
+
the calc silently resolved to `NaN`/`0` here until this bridge was added.
|
|
34
|
+
|
|
35
|
+
**Residual, not fixed:** the previous/next chevron control renders ~3.8px wider in mantine
|
|
36
|
+
(51.8px vs. mui's exact 48px square) — mantine's own icon-only nav button apparently doesn't
|
|
37
|
+
collapse fully to `min-width` the way mui's `PaginationItem` does. Pixel-matched everywhere else
|
|
38
|
+
(page-number circle size/color/border, selected state, ellipsis centering, chevron colors, hover
|
|
39
|
+
treatment, ripple removal, text labels) — not investigated further given the small, cosmetic
|
|
40
|
+
scope of this one remaining gap.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import styles from "./Pagination.module.css";
|
|
2
|
+
|
|
3
|
+
const NextPath =
|
|
4
|
+
"M8.781 8l-3.3-3.3.943-.943L10.667 8l-4.243 4.243-.943-.943 3.3-3.3z";
|
|
5
|
+
const PrevPath =
|
|
6
|
+
"M7.219 8l3.3 3.3-.943.943L5.333 8l4.243-4.243.943.943-3.3 3.3z";
|
|
7
|
+
const FirstPath =
|
|
8
|
+
"M6.85355 3.85355C7.04882 3.65829 7.04882 3.34171 6.85355 3.14645C6.65829 2.95118 6.34171 2.95118 6.14645 3.14645L2.14645 7.14645C1.95118 7.34171 1.95118 7.65829 2.14645 7.85355L6.14645 11.8536C6.34171 12.0488 6.65829 12.0488 6.85355 11.8536C7.04882 11.6583 7.04882 11.3417 6.85355 11.1464L3.20711 7.5L6.85355 3.85355ZM12.8536 3.85355C13.0488 3.65829 13.0488 3.34171 12.8536 3.14645C12.6583 2.95118 12.3417 2.95118 12.1464 3.14645L8.14645 7.14645C7.95118 7.34171 7.95118 7.65829 8.14645 7.85355L12.1464 11.8536C12.3417 12.0488 12.6583 12.0488 12.8536 11.8536C13.0488 11.6583 13.0488 11.3417 12.8536 11.1464L9.20711 7.5L12.8536 3.85355Z";
|
|
9
|
+
const LastPath =
|
|
10
|
+
"M2.14645 11.1464C1.95118 11.3417 1.95118 11.6583 2.14645 11.8536C2.34171 12.0488 2.65829 12.0488 2.85355 11.8536L6.85355 7.85355C7.04882 7.65829 7.04882 7.34171 6.85355 7.14645L2.85355 3.14645C2.65829 2.95118 2.34171 2.95118 2.14645 3.14645C1.95118 3.34171 1.95118 3.65829 2.14645 3.85355L5.79289 7.5L2.14645 11.1464ZM8.14645 11.1464C7.95118 11.3417 7.95118 11.6583 8.14645 11.8536C8.34171 12.0488 8.65829 12.0488 8.85355 11.8536L12.8536 7.85355C13.0488 7.65829 13.0488 7.34171 12.8536 7.14645L8.85355 3.14645C8.65829 2.95118 8.34171 2.95118 8.14645 3.14645C7.95118 3.34171 7.95118 3.65829 8.14645 3.85355L11.7929 7.5L8.14645 11.1464Z";
|
|
11
|
+
|
|
12
|
+
export type PaginationIconType = "next" | "prev" | "first" | "last";
|
|
13
|
+
|
|
14
|
+
const paths: Record<PaginationIconType, string> = {
|
|
15
|
+
next: NextPath,
|
|
16
|
+
prev: PrevPath,
|
|
17
|
+
first: FirstPath,
|
|
18
|
+
last: LastPath,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const PaginationIcon = ({
|
|
22
|
+
type,
|
|
23
|
+
className,
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<"svg"> & { type: PaginationIconType }) => (
|
|
26
|
+
<svg
|
|
27
|
+
viewBox="0 0 16 16"
|
|
28
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
29
|
+
className={`${styles.baseIcon} ${className || ""}`.trim()}
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
<path d={paths[type as PaginationIconType]} fill="currentColor" />
|
|
33
|
+
</svg>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
|
+
export const NextWithLabel = (props: any) => (
|
|
38
|
+
<div className={styles.iconWithLabel}>
|
|
39
|
+
<span>Next</span>
|
|
40
|
+
<PaginationIcon type="next" {...props} />
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
export const PrevWithLabel = (props: any) => (
|
|
46
|
+
<div className={styles.iconWithLabel}>
|
|
47
|
+
<PaginationIcon type="prev" {...props} />
|
|
48
|
+
<span>Prev</span>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
+
export const FirstWithLabel = (props: any) => (
|
|
54
|
+
<div className={styles.iconWithLabel}>
|
|
55
|
+
<PaginationIcon type="first" {...props} />
|
|
56
|
+
<span>First</span>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
export const LastWithLabel = (props: any) => (
|
|
62
|
+
<div className={styles.iconWithLabel}>
|
|
63
|
+
<span>Last</span>
|
|
64
|
+
<PaginationIcon type="last" {...props} />
|
|
65
|
+
</div>
|
|
66
|
+
);
|