@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,97 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Checkbox } from "./Checkbox";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Checkbox> = {
|
|
5
|
+
title: "UI-Kit/Checkbox",
|
|
6
|
+
component: Checkbox,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component: `
|
|
12
|
+
The \`Checkbox\` component is a precisely engineered, atomic form primitive representing boolean states natively aligned to the Recursica design system. It overrides Mantine's standard properties explicitly enforcing our variables natively across all structural boundaries.
|
|
13
|
+
|
|
14
|
+
> [!IMPORTANT]
|
|
15
|
+
> The atomic \`Checkbox\` is intended primarily as an internal primitive. **When wrapping multiple Checkbox elements together or rendering form controls, always utilize the \`<Checkbox.Group>\` component.** \`Checkbox.Group\` inherits the global \`FormControlWrapper\`, granting instantaneous access to macroscopic layout structuring, assistive descriptions, validation errors, and strict flex arrays.
|
|
16
|
+
|
|
17
|
+
### Usage
|
|
18
|
+
To render a solitary component natively:
|
|
19
|
+
\`\`\`tsx
|
|
20
|
+
<Checkbox label="Acknowledge Terms" defaultChecked />
|
|
21
|
+
\`\`\`
|
|
22
|
+
`,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
argTypes: {
|
|
27
|
+
disabled: {
|
|
28
|
+
control: "boolean",
|
|
29
|
+
},
|
|
30
|
+
readOnly: {
|
|
31
|
+
control: "boolean",
|
|
32
|
+
description:
|
|
33
|
+
"Toggles structural read-only data presentation bypassing interaction boundaries completely.",
|
|
34
|
+
},
|
|
35
|
+
controlMaxWidth: { table: { disable: true } },
|
|
36
|
+
controlMinWidth: { table: { disable: true } },
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default meta;
|
|
41
|
+
|
|
42
|
+
type Story = StoryObj<typeof Checkbox>;
|
|
43
|
+
|
|
44
|
+
export const Default: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
disabled: false,
|
|
47
|
+
label: "Standard Unchecked Property",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const SideBySideLayout: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
label: "Opt-in form alignment",
|
|
54
|
+
formLayout: "side-by-side",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const LongLabelWrap: Story = {
|
|
59
|
+
args: {
|
|
60
|
+
label:
|
|
61
|
+
"A meticulously long Checkbox label property demonstrating the absolute maximum 400px wrapper constraints actively snapping the text engine down onto a secondary wrapping line automatically without blowing out the visual boundaries.",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const StaticVariations: Story = {
|
|
66
|
+
args: {},
|
|
67
|
+
render: () => (
|
|
68
|
+
<div
|
|
69
|
+
style={{
|
|
70
|
+
display: "flex",
|
|
71
|
+
flexDirection: "column",
|
|
72
|
+
gap: "24px",
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
<Checkbox label="Default Unchecked State" />
|
|
76
|
+
<Checkbox label="Acknowledge Configuration" defaultChecked />
|
|
77
|
+
<Checkbox label="Indeterminate Master" indeterminate />
|
|
78
|
+
<Checkbox label="Disabled Variant" disabled />
|
|
79
|
+
<Checkbox label="Disabled Checked Variant" checked disabled />
|
|
80
|
+
</div>
|
|
81
|
+
),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const ReadOnly: Story = {
|
|
85
|
+
args: {},
|
|
86
|
+
render: () => (
|
|
87
|
+
<div
|
|
88
|
+
style={{
|
|
89
|
+
display: "flex",
|
|
90
|
+
flexDirection: "column",
|
|
91
|
+
gap: "24px",
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
<Checkbox label="Accept Terms & Conditions" defaultChecked readOnly />
|
|
95
|
+
</div>
|
|
96
|
+
),
|
|
97
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Placeholder for future Checkbox component tests. Add tests here if/when needed.
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Checkbox as MuiCheckbox,
|
|
4
|
+
type CheckboxProps as MuiCheckboxProps,
|
|
5
|
+
} from "@mui/material";
|
|
6
|
+
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
7
|
+
import { CheckboxGroup, CheckboxGroupContext } from "./CheckboxGroup";
|
|
8
|
+
import {
|
|
9
|
+
filterStylingProps,
|
|
10
|
+
omitUnsupportedProps,
|
|
11
|
+
mergeClassNames,
|
|
12
|
+
type RecursicaOverStyled,
|
|
13
|
+
} from "../../utils/filterStylingProps";
|
|
14
|
+
import {
|
|
15
|
+
type RequireAccessibleLabel,
|
|
16
|
+
type RecursicaCheckboxProps,
|
|
17
|
+
} from "@recursica/adapter-common";
|
|
18
|
+
import {
|
|
19
|
+
FormControlLayout,
|
|
20
|
+
type FormControlLayoutProps,
|
|
21
|
+
} from "../FormControlLayout/FormControlLayout";
|
|
22
|
+
import { AssistiveElement } from "../AssistiveElement/AssistiveElement";
|
|
23
|
+
|
|
24
|
+
import styles from "./Checkbox.module.css";
|
|
25
|
+
|
|
26
|
+
export type CheckboxWrapperProps = Omit<MuiCheckboxProps, "size" | "color"> &
|
|
27
|
+
RecursicaCheckboxProps &
|
|
28
|
+
ReadOnlyControlProps &
|
|
29
|
+
Pick<
|
|
30
|
+
FormControlLayoutProps,
|
|
31
|
+
"formLayout" | "labelSize" | "controlMaxWidth" | "controlMinWidth"
|
|
32
|
+
>;
|
|
33
|
+
|
|
34
|
+
export type RecursicaCheckboxPropsAlias =
|
|
35
|
+
RequireAccessibleLabel<CheckboxWrapperProps>;
|
|
36
|
+
|
|
37
|
+
export type CheckboxProps = RecursicaOverStyled<RecursicaCheckboxPropsAlias>;
|
|
38
|
+
|
|
39
|
+
type CheckboxComponent = React.ForwardRefExoticComponent<
|
|
40
|
+
CheckboxProps & React.RefAttributes<HTMLButtonElement>
|
|
41
|
+
> & {
|
|
42
|
+
Group: typeof CheckboxGroup;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(
|
|
46
|
+
function Checkbox(props, ref) {
|
|
47
|
+
const {
|
|
48
|
+
overStyled = false,
|
|
49
|
+
readOnly,
|
|
50
|
+
readOnlyComponent,
|
|
51
|
+
disabled,
|
|
52
|
+
formLayout,
|
|
53
|
+
labelSize,
|
|
54
|
+
controlMaxWidth,
|
|
55
|
+
controlMinWidth,
|
|
56
|
+
label,
|
|
57
|
+
description,
|
|
58
|
+
error,
|
|
59
|
+
style,
|
|
60
|
+
...rest
|
|
61
|
+
} = props;
|
|
62
|
+
|
|
63
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
64
|
+
// through even if a caller forces them via plain JavaScript, bypassing the Omit<> above.
|
|
65
|
+
const UNSUPPORTED_PROPS = [
|
|
66
|
+
"size", // Recursica controls sizing via design tokens, not MUI's native small/medium size
|
|
67
|
+
"color", // Colors are token-driven; MUI's native palette isn't exposed
|
|
68
|
+
] as const satisfies readonly (keyof MuiCheckboxProps)[];
|
|
69
|
+
|
|
70
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
71
|
+
filterStylingProps(rest, overStyled),
|
|
72
|
+
UNSUPPORTED_PROPS,
|
|
73
|
+
);
|
|
74
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
75
|
+
|
|
76
|
+
const mergedClassNames = mergeClassNames(
|
|
77
|
+
{
|
|
78
|
+
root: styles.root,
|
|
79
|
+
checked: styles.checked,
|
|
80
|
+
disabled: styles.disabled,
|
|
81
|
+
},
|
|
82
|
+
restRecord.classes as Partial<Record<string, string>> | undefined,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const classNameProp = restRecord.className as string | undefined;
|
|
86
|
+
const finalClass = classNameProp
|
|
87
|
+
? `${styles.root} ${classNameProp}`
|
|
88
|
+
: styles.root;
|
|
89
|
+
|
|
90
|
+
const groupContext = React.useContext(CheckboxGroupContext);
|
|
91
|
+
// A Checkbox with its own explicit `checked` prop owns its source of truth even when
|
|
92
|
+
// nested inside a CheckboxGroup used purely for layout (e.g. TransferList's ungrouped
|
|
93
|
+
// rows) — only defer to the group's value array when the caller hasn't already told us.
|
|
94
|
+
const isGrouped = groupContext !== null && restRecord.checked === undefined;
|
|
95
|
+
const isGroupReadOnly = isGrouped ? groupContext.readOnly : false;
|
|
96
|
+
const isChecked = isGrouped
|
|
97
|
+
? (groupContext.value || []).includes(restRecord.value)
|
|
98
|
+
: !!(restRecord.checked ?? restRecord.defaultChecked);
|
|
99
|
+
// Only force controlled mode when we actually own the source of truth (grouped) or the
|
|
100
|
+
// caller explicitly passed `checked` (controlled). A plain `defaultChecked`/neither-prop
|
|
101
|
+
// usage must stay uncontrolled — otherwise `checked` gets pinned to a value that never
|
|
102
|
+
// updates, and MUI's native input silently snaps back after every click. Mirrors Switch's
|
|
103
|
+
// identical `isGrouped ? { checked: ... } : {}` pattern (Switch never had this bug).
|
|
104
|
+
const isControlled = isGrouped || restRecord.checked !== undefined;
|
|
105
|
+
|
|
106
|
+
if (readOnly && !!readOnlyComponent) {
|
|
107
|
+
const ReadOnlyComp = readOnlyComponent;
|
|
108
|
+
const roNode = (
|
|
109
|
+
<ReadOnlyComp
|
|
110
|
+
{...props}
|
|
111
|
+
checked={isChecked}
|
|
112
|
+
label={label as React.ReactNode}
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (formLayout) {
|
|
117
|
+
return (
|
|
118
|
+
<FormControlLayout
|
|
119
|
+
formLayout={formLayout}
|
|
120
|
+
labelSize={labelSize}
|
|
121
|
+
controlMaxWidth={controlMaxWidth}
|
|
122
|
+
controlMinWidth={controlMinWidth}
|
|
123
|
+
>
|
|
124
|
+
{roNode}
|
|
125
|
+
</FormControlLayout>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return <>{roNode}</>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
133
|
+
if (isGrouped) {
|
|
134
|
+
const newValue = e.target.checked
|
|
135
|
+
? [...(groupContext.value || []), restRecord.value]
|
|
136
|
+
: (groupContext.value || []).filter((v) => v !== restRecord.value);
|
|
137
|
+
if (groupContext.onChange) {
|
|
138
|
+
groupContext.onChange(e, newValue);
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
if (restRecord.onChange) {
|
|
142
|
+
(
|
|
143
|
+
restRecord.onChange as (
|
|
144
|
+
event: React.ChangeEvent<HTMLInputElement>,
|
|
145
|
+
checked: boolean,
|
|
146
|
+
) => void
|
|
147
|
+
)(e, e.target.checked);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const CheckIcon = (props: React.ComponentProps<"svg">) => (
|
|
153
|
+
<svg
|
|
154
|
+
viewBox="0 0 10 7"
|
|
155
|
+
fill="none"
|
|
156
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
157
|
+
{...props}
|
|
158
|
+
>
|
|
159
|
+
<path
|
|
160
|
+
d="M4 4.586L1.707 2.293A1 1 0 1 0 .293 3.707l3 3a.997.997 0 0 0 1.414 0l5-5A1 1 0 1 0 8.293.293L4 4.586z"
|
|
161
|
+
fill="currentColor"
|
|
162
|
+
fillRule="evenodd"
|
|
163
|
+
clipRule="evenodd"
|
|
164
|
+
/>
|
|
165
|
+
</svg>
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const checkboxNode = (
|
|
169
|
+
<MuiCheckbox
|
|
170
|
+
ref={ref}
|
|
171
|
+
{...(sanitizedProps as unknown as MuiCheckboxProps)}
|
|
172
|
+
className={!label ? `${finalClass} ${styles.inner}` : styles.inner}
|
|
173
|
+
classes={mergedClassNames}
|
|
174
|
+
disabled={readOnly || disabled || isGroupReadOnly}
|
|
175
|
+
{...(isControlled ? { checked: isChecked as boolean } : {})}
|
|
176
|
+
onChange={handleChange}
|
|
177
|
+
disableRipple
|
|
178
|
+
sx={label ? { padding: 0 } : undefined}
|
|
179
|
+
icon={<div className={styles.input} />}
|
|
180
|
+
checkedIcon={
|
|
181
|
+
<div className={`${styles.input} ${styles.inputChecked}`}>
|
|
182
|
+
<CheckIcon className={styles.icon} />
|
|
183
|
+
</div>
|
|
184
|
+
}
|
|
185
|
+
indeterminateIcon={
|
|
186
|
+
<div className={`${styles.input} ${styles.inputIndeterminate}`}>
|
|
187
|
+
<svg
|
|
188
|
+
className={styles.icon}
|
|
189
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
190
|
+
fill="none"
|
|
191
|
+
viewBox="0 0 32 32"
|
|
192
|
+
>
|
|
193
|
+
<rect x="6" y="14" width="20" height="4" fill="currentColor" />
|
|
194
|
+
</svg>
|
|
195
|
+
</div>
|
|
196
|
+
}
|
|
197
|
+
/>
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const finalNode = label ? (
|
|
201
|
+
<div className={finalClass} style={style as React.CSSProperties}>
|
|
202
|
+
<div className={styles.body}>
|
|
203
|
+
{checkboxNode}
|
|
204
|
+
<div className={styles.labelWrapper}>
|
|
205
|
+
<label
|
|
206
|
+
className={styles.label}
|
|
207
|
+
htmlFor={restRecord.id as string}
|
|
208
|
+
data-disabled={
|
|
209
|
+
readOnly || disabled || isGroupReadOnly ? true : undefined
|
|
210
|
+
}
|
|
211
|
+
>
|
|
212
|
+
{label as React.ReactNode}
|
|
213
|
+
</label>
|
|
214
|
+
{/* description/error are mutually exclusive — error takes precedence */}
|
|
215
|
+
{error ? (
|
|
216
|
+
<AssistiveElement
|
|
217
|
+
assistiveVariant="error"
|
|
218
|
+
assistiveWithIcon={false}
|
|
219
|
+
>
|
|
220
|
+
{error}
|
|
221
|
+
</AssistiveElement>
|
|
222
|
+
) : (
|
|
223
|
+
description && (
|
|
224
|
+
<AssistiveElement
|
|
225
|
+
assistiveVariant="help"
|
|
226
|
+
assistiveWithIcon={false}
|
|
227
|
+
>
|
|
228
|
+
{description}
|
|
229
|
+
</AssistiveElement>
|
|
230
|
+
)
|
|
231
|
+
)}
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
) : (
|
|
236
|
+
<div className={finalClass} style={style as React.CSSProperties}>
|
|
237
|
+
{checkboxNode}
|
|
238
|
+
</div>
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
if (formLayout) {
|
|
242
|
+
return (
|
|
243
|
+
<FormControlLayout
|
|
244
|
+
formLayout={formLayout}
|
|
245
|
+
labelSize={labelSize}
|
|
246
|
+
controlMaxWidth={controlMaxWidth}
|
|
247
|
+
controlMinWidth={controlMinWidth}
|
|
248
|
+
>
|
|
249
|
+
{finalNode}
|
|
250
|
+
</FormControlLayout>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return finalNode;
|
|
255
|
+
},
|
|
256
|
+
) as CheckboxComponent;
|
|
257
|
+
|
|
258
|
+
Checkbox.displayName = "Checkbox";
|
|
259
|
+
Checkbox.Group = CheckboxGroup;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Checkbox } from "./Checkbox";
|
|
3
|
+
import { CheckboxGroup } from "./CheckboxGroup";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof CheckboxGroup> = {
|
|
8
|
+
title: "UI-Kit/CheckboxGroup",
|
|
9
|
+
component: CheckboxGroup,
|
|
10
|
+
tags: ["autodocs"],
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component: `
|
|
15
|
+
The \`CheckboxGroup\` component is the mandatory organizational wrapper aggregating multiple \`Checkbox\` primitives into structurally bound unified arrays. It inherently leverages the \`FormControlWrapper\` granting native access to macroscopic layout structuring, assistive descriptions, and strict flex arrays.
|
|
16
|
+
|
|
17
|
+
We exclusively utilize the \`formLayout\` parameter to control macro-level form flow:
|
|
18
|
+
- **\`formLayout="stacked"\`**: Top-to-bottom layout cascading the Label bounding box down vertically into a standard stacked checkbox column array.
|
|
19
|
+
- **\`formLayout="side-by-side"\`**: Flow architecture pulling the grouping Label dynamically to the left while structurally organizing the internal checkboxes cleanly alongside it horizontally.
|
|
20
|
+
|
|
21
|
+
\`\`\`tsx
|
|
22
|
+
<Checkbox.Group
|
|
23
|
+
label="Execution Targets"
|
|
24
|
+
assistiveText="Strictly mapped structural grouping dynamically applied natively."
|
|
25
|
+
formLayout="stacked"
|
|
26
|
+
>
|
|
27
|
+
<Checkbox value="react" label="Browser Execution Context" />
|
|
28
|
+
<Checkbox value="svelte" label="Edge Nodes" />
|
|
29
|
+
</Checkbox.Group>
|
|
30
|
+
\`\`\`
|
|
31
|
+
`,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
argTypes: {
|
|
36
|
+
...formControlArgTypes,
|
|
37
|
+
readOnly: {
|
|
38
|
+
control: "boolean",
|
|
39
|
+
description:
|
|
40
|
+
"Toggles structural read-only data presentation bypassing interaction boundaries completely.",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default meta;
|
|
46
|
+
|
|
47
|
+
type Story = StoryObj<typeof CheckboxGroup>;
|
|
48
|
+
|
|
49
|
+
export const Default: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
formLayout: "stacked",
|
|
52
|
+
label: "Standard Group",
|
|
53
|
+
},
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
55
|
+
render: function StoryRender({ withLayer, layer, ...args }: any) {
|
|
56
|
+
const [value, setValue] = useState<string[]>([]);
|
|
57
|
+
return (
|
|
58
|
+
<Checkbox.Group {...args} value={value} onChange={setValue}>
|
|
59
|
+
<Checkbox value="1" label="Option 1" />
|
|
60
|
+
<Checkbox value="2" label="Option 2" />
|
|
61
|
+
</Checkbox.Group>
|
|
62
|
+
);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const SideBySideLayout: Story = {
|
|
67
|
+
args: {
|
|
68
|
+
formLayout: "side-by-side",
|
|
69
|
+
labelOptionalText: "Recommended",
|
|
70
|
+
labelWithEditIcon: true,
|
|
71
|
+
label: "Frontend Frameworks",
|
|
72
|
+
assistiveText:
|
|
73
|
+
"Select all libraries currently in use for this specific workspace configuration.",
|
|
74
|
+
},
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
76
|
+
render: function StoryRender({ withLayer, layer, ...args }: any) {
|
|
77
|
+
const [value, setValue] = useState<string[]>(["react"]);
|
|
78
|
+
return (
|
|
79
|
+
<Checkbox.Group {...args} value={value} onChange={setValue}>
|
|
80
|
+
<Checkbox value="react" label="React (Standard Build)" />
|
|
81
|
+
<Checkbox
|
|
82
|
+
value="svelte"
|
|
83
|
+
label="The Svelte architecture which provides a highly optimized, completely compiler-driven framework avoiding virtual DOM boundaries. This massively extended text explicitly guarantees accurate wrapper constraint checking and multi-line flex alignment."
|
|
84
|
+
/>
|
|
85
|
+
<Checkbox value="vue" label="Vue Configuration Map" />
|
|
86
|
+
</Checkbox.Group>
|
|
87
|
+
);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const StackedLayout: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
formLayout: "stacked",
|
|
94
|
+
required: true,
|
|
95
|
+
label: "Execution Targets",
|
|
96
|
+
error: "You must select at least one deployment target to compile.",
|
|
97
|
+
},
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
99
|
+
render: function StoryRender({ withLayer, layer, ...args }: any) {
|
|
100
|
+
const [value, setValue] = useState<string[]>(["react"]);
|
|
101
|
+
return (
|
|
102
|
+
<Checkbox.Group {...args} value={value} onChange={setValue}>
|
|
103
|
+
<Checkbox value="react" label="Browser Execution Context" />
|
|
104
|
+
<Checkbox
|
|
105
|
+
value="svelte"
|
|
106
|
+
label="Highly distributed Edge computing environments seamlessly bridging local runtime boundaries."
|
|
107
|
+
/>
|
|
108
|
+
<Checkbox value="vue" label="Serverless Cloud Providers" />
|
|
109
|
+
</Checkbox.Group>
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const ReadOnly: Story = {
|
|
115
|
+
args: {
|
|
116
|
+
readOnly: true,
|
|
117
|
+
formLayout: "stacked",
|
|
118
|
+
required: true,
|
|
119
|
+
label: "Static ReadOnly Execution Locks",
|
|
120
|
+
assistiveText:
|
|
121
|
+
"This structure explicitly validates native component-level DOM preservation natively mapping lock bounds safely over interaction.",
|
|
122
|
+
},
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
124
|
+
render: function StoryRender({ withLayer, layer, ...args }: any) {
|
|
125
|
+
const [value, setValue] = useState<string[]>(["disabledNode"]);
|
|
126
|
+
return (
|
|
127
|
+
<Checkbox.Group {...args} value={value} onChange={setValue}>
|
|
128
|
+
<Checkbox
|
|
129
|
+
value="disabledNode"
|
|
130
|
+
label="Structurally Checked Node natively"
|
|
131
|
+
/>
|
|
132
|
+
<Checkbox
|
|
133
|
+
value="disabledNodeEmpty"
|
|
134
|
+
label="Unchecked Configuration Limit"
|
|
135
|
+
/>
|
|
136
|
+
</Checkbox.Group>
|
|
137
|
+
);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React, { forwardRef } from "react";
|
|
3
|
+
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
4
|
+
import {
|
|
5
|
+
filterStylingProps,
|
|
6
|
+
type RecursicaOverStyled,
|
|
7
|
+
} from "../../utils/filterStylingProps";
|
|
8
|
+
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
9
|
+
import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
|
|
10
|
+
import styles from "./Checkbox.module.css";
|
|
11
|
+
|
|
12
|
+
import { FormGroup as MuiFormGroup } from "@mui/material";
|
|
13
|
+
|
|
14
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
15
|
+
export const CheckboxGroupContext = React.createContext<{
|
|
16
|
+
value?: any[];
|
|
17
|
+
onChange?: (event: React.SyntheticEvent, value: any) => void;
|
|
18
|
+
name?: string;
|
|
19
|
+
readOnly?: boolean;
|
|
20
|
+
} | null>(null);
|
|
21
|
+
|
|
22
|
+
import { type RecursicaCheckboxGroupProps as BaseRecursicaCheckboxGroupProps } from "@recursica/adapter-common";
|
|
23
|
+
|
|
24
|
+
export interface RecursicaCheckboxGroupProps
|
|
25
|
+
extends Omit<
|
|
26
|
+
React.HTMLAttributes<HTMLDivElement>,
|
|
27
|
+
"onChange" | "defaultValue"
|
|
28
|
+
>,
|
|
29
|
+
Omit<
|
|
30
|
+
RecursicaFormControlWrapperProps,
|
|
31
|
+
| "controlMaxWidth"
|
|
32
|
+
| "controlMinWidth"
|
|
33
|
+
| "onChange"
|
|
34
|
+
| "classes"
|
|
35
|
+
| "withAsterisk"
|
|
36
|
+
| "defaultValue"
|
|
37
|
+
>,
|
|
38
|
+
ReadOnlyControlProps,
|
|
39
|
+
BaseRecursicaCheckboxGroupProps {
|
|
40
|
+
// MUI has no native checkbox-group concept to match (its own `FormGroup` is layout-only,
|
|
41
|
+
// no value/onChange) — this signature is Recursica's own, same as TransferList/Accordion.
|
|
42
|
+
onChange?: (value: unknown[]) => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type CheckboxGroupProps =
|
|
46
|
+
RecursicaOverStyled<RecursicaCheckboxGroupProps>;
|
|
47
|
+
|
|
48
|
+
export const CheckboxGroup = forwardRef<HTMLDivElement, CheckboxGroupProps>(
|
|
49
|
+
function CheckboxGroup(props, ref) {
|
|
50
|
+
const {
|
|
51
|
+
overStyled = false,
|
|
52
|
+
formLayout = "stacked",
|
|
53
|
+
|
|
54
|
+
// Label Wrappers
|
|
55
|
+
labelSize,
|
|
56
|
+
labelAlignment,
|
|
57
|
+
labelOptionalText,
|
|
58
|
+
labelWithEditIcon,
|
|
59
|
+
onLabelEditClick,
|
|
60
|
+
|
|
61
|
+
// Base Mantine Extracted Attributes
|
|
62
|
+
label,
|
|
63
|
+
description,
|
|
64
|
+
assistiveText,
|
|
65
|
+
assistiveWithIcon,
|
|
66
|
+
error,
|
|
67
|
+
required,
|
|
68
|
+
// removed withAsterisk
|
|
69
|
+
id,
|
|
70
|
+
className,
|
|
71
|
+
style,
|
|
72
|
+
children,
|
|
73
|
+
readOnly,
|
|
74
|
+
readOnlyComponent,
|
|
75
|
+
emptyValueComponent,
|
|
76
|
+
value,
|
|
77
|
+
defaultValue,
|
|
78
|
+
onChange,
|
|
79
|
+
...rest
|
|
80
|
+
} = props;
|
|
81
|
+
// NOTE: this component's props surface (HTMLAttributes<HTMLDivElement>-based) has no native
|
|
82
|
+
// "size" (or other Recursica-unsupported) prop to leak through here — nothing to add to an
|
|
83
|
+
// UNSUPPORTED_PROPS list beyond what filterStylingProps already blocks.
|
|
84
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
85
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
86
|
+
|
|
87
|
+
const handleChange = (_event: React.SyntheticEvent, childValue: any) => {
|
|
88
|
+
if (onChange) {
|
|
89
|
+
onChange(childValue);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<WithReadOnlyWrapper
|
|
95
|
+
className={className}
|
|
96
|
+
style={style as React.CSSProperties}
|
|
97
|
+
// Not the group's own row width: this token caps a single checkbox+its own label
|
|
98
|
+
// (applied per-item in Checkbox.module.css's `.root`). The group has no max-width token
|
|
99
|
+
// of its own in the schema, so this must stay undefined or FormControlLayout caps the
|
|
100
|
+
// whole label+items row (including the group's own label) at 400px in side-by-side layout.
|
|
101
|
+
controlMaxWidth={undefined}
|
|
102
|
+
controlMinWidth={undefined}
|
|
103
|
+
overStyled={overStyled as true}
|
|
104
|
+
// strictly override
|
|
105
|
+
formLayout={formLayout}
|
|
106
|
+
labelSize={labelSize}
|
|
107
|
+
labelAlignment={labelAlignment}
|
|
108
|
+
labelOptionalText={labelOptionalText}
|
|
109
|
+
labelWithEditIcon={labelWithEditIcon}
|
|
110
|
+
onLabelEditClick={onLabelEditClick}
|
|
111
|
+
label={label}
|
|
112
|
+
description={description}
|
|
113
|
+
assistiveText={assistiveText}
|
|
114
|
+
assistiveWithIcon={assistiveWithIcon}
|
|
115
|
+
error={error}
|
|
116
|
+
required={required}
|
|
117
|
+
id={id}
|
|
118
|
+
readOnly={readOnly && !!readOnlyComponent}
|
|
119
|
+
readOnlyComponent={readOnlyComponent}
|
|
120
|
+
emptyValueComponent={emptyValueComponent}
|
|
121
|
+
readOnlyType="text"
|
|
122
|
+
readOnlyValue={value !== undefined ? value : defaultValue}
|
|
123
|
+
readOnlyNativeProps={props}
|
|
124
|
+
activeComponent={
|
|
125
|
+
<CheckboxGroupContext.Provider
|
|
126
|
+
value={{
|
|
127
|
+
value: (value !== undefined ? value : defaultValue) as any[],
|
|
128
|
+
onChange: handleChange,
|
|
129
|
+
name: restRecord.name as string | undefined,
|
|
130
|
+
readOnly: readOnly || !!(restRecord as any).disabled,
|
|
131
|
+
}}
|
|
132
|
+
>
|
|
133
|
+
<MuiFormGroup
|
|
134
|
+
ref={ref}
|
|
135
|
+
{...(sanitizedProps as any)}
|
|
136
|
+
className={`${styles.groupRoot} ${(sanitizedProps as any).className || ""}`.trim()}
|
|
137
|
+
data-layout={formLayout}
|
|
138
|
+
>
|
|
139
|
+
{children}
|
|
140
|
+
</MuiFormGroup>
|
|
141
|
+
</CheckboxGroupContext.Provider>
|
|
142
|
+
}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
CheckboxGroup.displayName = "CheckboxGroup";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Checkbox - Usage Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to integrate and use the `Checkbox` component in your projects using `@recursica/adapter-mui-v7`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Import Reference
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Checkbox } from "@recursica/adapter-mui-v7";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Basic Example
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { Checkbox } from "@recursica/adapter-mui-v7";
|
|
20
|
+
|
|
21
|
+
export default function Demo() {
|
|
22
|
+
return <Checkbox label="Accept terms and conditions" defaultChecked />;
|
|
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.
|