@brcarddev/frontend-commons 1.0.2
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/README.md +241 -0
- package/eslint.config.js +190 -0
- package/package.json +161 -0
- package/src/components/atoms/AudioPlayer/audio-player.stories.tsx +36 -0
- package/src/components/atoms/AudioPlayer/audio-player.test.tsx +20 -0
- package/src/components/atoms/AudioPlayer/audio-player.tsx +13 -0
- package/src/components/atoms/AudioPlayer/index.ts +1 -0
- package/src/components/atoms/Badge/badge.stories.tsx +80 -0
- package/src/components/atoms/Badge/badge.test.tsx +59 -0
- package/src/components/atoms/Badge/badge.tsx +47 -0
- package/src/components/atoms/Badge/index.ts +1 -0
- package/src/components/atoms/Box/box.stories.tsx +37 -0
- package/src/components/atoms/Box/box.test.tsx +47 -0
- package/src/components/atoms/Box/box.tsx +7 -0
- package/src/components/atoms/Box/index.ts +1 -0
- package/src/components/atoms/Button/button.stories.tsx +108 -0
- package/src/components/atoms/Button/button.test.tsx +54 -0
- package/src/components/atoms/Button/button.tsx +96 -0
- package/src/components/atoms/Button/index.ts +1 -0
- package/src/components/atoms/ButtonUpload/button-upload.stories.tsx +137 -0
- package/src/components/atoms/ButtonUpload/button-upload.tsx +304 -0
- package/src/components/atoms/ButtonUpload/index.ts +1 -0
- package/src/components/atoms/Calendar/calendar.stories.tsx +51 -0
- package/src/components/atoms/Calendar/calendar.test.tsx +41 -0
- package/src/components/atoms/Calendar/calendar.tsx +107 -0
- package/src/components/atoms/Calendar/index.ts +1 -0
- package/src/components/atoms/CheckIcon/check-icon.stories.tsx +38 -0
- package/src/components/atoms/CheckIcon/check-icon.test.tsx +270 -0
- package/src/components/atoms/CheckIcon/check-icon.tsx +141 -0
- package/src/components/atoms/CheckIcon/index.ts +1 -0
- package/src/components/atoms/Checkbox/checkbox.stories.tsx +133 -0
- package/src/components/atoms/Checkbox/checkbox.test.tsx +70 -0
- package/src/components/atoms/Checkbox/checkbox.tsx +31 -0
- package/src/components/atoms/Checkbox/index.ts +1 -0
- package/src/components/atoms/Flex/flex.stories.tsx +33 -0
- package/src/components/atoms/Flex/flex.test.tsx +47 -0
- package/src/components/atoms/Flex/flex.tsx +7 -0
- package/src/components/atoms/Flex/index.ts +1 -0
- package/src/components/atoms/Grid/grid.stories.tsx +33 -0
- package/src/components/atoms/Grid/grid.test.tsx +47 -0
- package/src/components/atoms/Grid/grid.tsx +7 -0
- package/src/components/atoms/Grid/index.ts +1 -0
- package/src/components/atoms/Icon/icon.stories.tsx +169 -0
- package/src/components/atoms/Icon/icon.test.tsx +272 -0
- package/src/components/atoms/Icon/icon.tsx +119 -0
- package/src/components/atoms/Icon/index.ts +1 -0
- package/src/components/atoms/Input/index.ts +1 -0
- package/src/components/atoms/Input/input.stories.tsx +704 -0
- package/src/components/atoms/Input/input.test.tsx +86 -0
- package/src/components/atoms/Input/input.tsx +161 -0
- package/src/components/atoms/InputMoney/index.ts +2 -0
- package/src/components/atoms/InputMoney/input-money.stories.tsx +240 -0
- package/src/components/atoms/InputMoney/input-money.test.tsx +98 -0
- package/src/components/atoms/InputMoney/input-money.tsx +254 -0
- package/src/components/atoms/InputPhone/index.ts +2 -0
- package/src/components/atoms/InputPhone/input-phone.stories.tsx +447 -0
- package/src/components/atoms/InputPhone/input-phone.test.tsx +148 -0
- package/src/components/atoms/InputPhone/input-phone.tsx +267 -0
- package/src/components/atoms/InputSearch/index.ts +2 -0
- package/src/components/atoms/InputSearch/input-search.stories.tsx +360 -0
- package/src/components/atoms/InputSearch/input-search.test.tsx +239 -0
- package/src/components/atoms/InputSearch/input-search.tsx +210 -0
- package/src/components/atoms/InputUpload/index.ts +1 -0
- package/src/components/atoms/InputUpload/input-upload.stories.tsx +229 -0
- package/src/components/atoms/InputUpload/input-upload.test.tsx +556 -0
- package/src/components/atoms/InputUpload/input-upload.tsx +434 -0
- package/src/components/atoms/InputWithButton/index.ts +2 -0
- package/src/components/atoms/InputWithButton/input-with-button.stories.tsx +503 -0
- package/src/components/atoms/InputWithButton/input-with-button.test.tsx +128 -0
- package/src/components/atoms/InputWithButton/input-with-button.tsx +170 -0
- package/src/components/atoms/Label/index.ts +1 -0
- package/src/components/atoms/Label/label.stories.tsx +90 -0
- package/src/components/atoms/Label/label.test.tsx +59 -0
- package/src/components/atoms/Label/label.tsx +43 -0
- package/src/components/atoms/Progress/index.ts +1 -0
- package/src/components/atoms/Progress/progress.stories.tsx +30 -0
- package/src/components/atoms/Progress/progress.test.tsx +63 -0
- package/src/components/atoms/Progress/progress.tsx +32 -0
- package/src/components/atoms/RenderCondition/index.ts +1 -0
- package/src/components/atoms/RenderCondition/render-condition.stories.tsx +28 -0
- package/src/components/atoms/RenderCondition/render-condition.test.tsx +27 -0
- package/src/components/atoms/RenderCondition/render-condition.tsx +9 -0
- package/src/components/atoms/RichTextEditor/index.ts +1 -0
- package/src/components/atoms/RichTextEditor/rich-text-editor.stories.tsx +214 -0
- package/src/components/atoms/RichTextEditor/rich-text-editor.test.tsx +442 -0
- package/src/components/atoms/RichTextEditor/rich-text-editor.tsx +202 -0
- package/src/components/atoms/Separator/index.ts +1 -0
- package/src/components/atoms/Separator/separator.stories.tsx +117 -0
- package/src/components/atoms/Separator/separator.test.tsx +50 -0
- package/src/components/atoms/Separator/separator.tsx +28 -0
- package/src/components/atoms/Skeleton/index.ts +1 -0
- package/src/components/atoms/Skeleton/skeleton.stories.tsx +84 -0
- package/src/components/atoms/Skeleton/skeleton.test.tsx +39 -0
- package/src/components/atoms/Skeleton/skeleton.tsx +14 -0
- package/src/components/atoms/Slider/index.ts +1 -0
- package/src/components/atoms/Slider/slider.stories.tsx +28 -0
- package/src/components/atoms/Slider/slider.test.tsx +90 -0
- package/src/components/atoms/Slider/slider.tsx +54 -0
- package/src/components/atoms/Sonner/index.ts +1 -0
- package/src/components/atoms/Sonner/sonner.css +39 -0
- package/src/components/atoms/Sonner/sonner.stories.tsx +261 -0
- package/src/components/atoms/Sonner/sonner.test.tsx +24 -0
- package/src/components/atoms/Sonner/sonner.tsx +13 -0
- package/src/components/atoms/Switch/index.ts +1 -0
- package/src/components/atoms/Switch/switch.stories.tsx +128 -0
- package/src/components/atoms/Switch/switch.test.tsx +70 -0
- package/src/components/atoms/Switch/switch.tsx +61 -0
- package/src/components/atoms/Textarea/index.ts +1 -0
- package/src/components/atoms/Textarea/textarea.stories.tsx +169 -0
- package/src/components/atoms/Textarea/textarea.test.tsx +56 -0
- package/src/components/atoms/Textarea/textarea.tsx +26 -0
- package/src/components/atoms/Toggle/index.ts +1 -0
- package/src/components/atoms/Toggle/toggle.stories.tsx +170 -0
- package/src/components/atoms/Toggle/toggle.test.tsx +62 -0
- package/src/components/atoms/Toggle/toggle.tsx +47 -0
- package/src/components/atoms/Typography/index.ts +1 -0
- package/src/components/atoms/Typography/typography.stories.tsx +95 -0
- package/src/components/atoms/Typography/typography.test.tsx +66 -0
- package/src/components/atoms/Typography/typography.tsx +63 -0
- package/src/components/atoms/UploadImageField/index.ts +1 -0
- package/src/components/atoms/UploadImageField/upload-image-field.stories.tsx +249 -0
- package/src/components/atoms/UploadImageField/upload-image-field.test.tsx +348 -0
- package/src/components/atoms/UploadImageField/upload-image-field.tsx +362 -0
- package/src/components/atoms/VideoPlayer/index.ts +1 -0
- package/src/components/atoms/VideoPlayer/video-player.stories.tsx +37 -0
- package/src/components/atoms/VideoPlayer/video-player.test.tsx +20 -0
- package/src/components/atoms/VideoPlayer/video-player.tsx +26 -0
- package/src/components/atoms/index.ts +31 -0
- package/src/components/icons/alert-circle.tsx +22 -0
- package/src/components/icons/align-center.tsx +22 -0
- package/src/components/icons/align-left.tsx +22 -0
- package/src/components/icons/annotation-dots.tsx +16 -0
- package/src/components/icons/annotation-question.tsx +15 -0
- package/src/components/icons/annotation.tsx +22 -0
- package/src/components/icons/announcement-01.tsx +15 -0
- package/src/components/icons/announcement-02.tsx +15 -0
- package/src/components/icons/apple-logo.tsx +9 -0
- package/src/components/icons/arrow-circle-broken-right.tsx +16 -0
- package/src/components/icons/arrow-down.tsx +9 -0
- package/src/components/icons/arrow-up.tsx +9 -0
- package/src/components/icons/at-sign.tsx +21 -0
- package/src/components/icons/award-01.tsx +15 -0
- package/src/components/icons/award-03.tsx +16 -0
- package/src/components/icons/bank-note-01.tsx +15 -0
- package/src/components/icons/bar-chart-square-02.tsx +9 -0
- package/src/components/icons/bell-01.tsx +9 -0
- package/src/components/icons/bell-04.tsx +16 -0
- package/src/components/icons/bold-01.tsx +22 -0
- package/src/components/icons/book-open-01.tsx +15 -0
- package/src/components/icons/brackets-ellipses.tsx +22 -0
- package/src/components/icons/briefcase-01.tsx +9 -0
- package/src/components/icons/brush-01.tsx +22 -0
- package/src/components/icons/building-02.tsx +9 -0
- package/src/components/icons/building-06.tsx +9 -0
- package/src/components/icons/calendar-minus-02.tsx +15 -0
- package/src/components/icons/calendar.tsx +9 -0
- package/src/components/icons/certificate-01.tsx +16 -0
- package/src/components/icons/chart-breakout-square.tsx +16 -0
- package/src/components/icons/check-circle-02.tsx +16 -0
- package/src/components/icons/check-circle.tsx +15 -0
- package/src/components/icons/check.tsx +21 -0
- package/src/components/icons/chevron-down-double.tsx +16 -0
- package/src/components/icons/chevron-down.tsx +9 -0
- package/src/components/icons/chevron-left-double.tsx +22 -0
- package/src/components/icons/chevron-left.tsx +16 -0
- package/src/components/icons/chevron-right-double.tsx +22 -0
- package/src/components/icons/chevron-right.tsx +16 -0
- package/src/components/icons/chevron-up-double.tsx +16 -0
- package/src/components/icons/clock-rewind.tsx +15 -0
- package/src/components/icons/clock-stopwatch.tsx +15 -0
- package/src/components/icons/coins-hand.tsx +15 -0
- package/src/components/icons/coins-stacked-01.tsx +15 -0
- package/src/components/icons/coins-stacked-02.tsx +15 -0
- package/src/components/icons/container.tsx +9 -0
- package/src/components/icons/copy-02.tsx +16 -0
- package/src/components/icons/copy-04.tsx +21 -0
- package/src/components/icons/corner-down-right.tsx +9 -0
- package/src/components/icons/countries/br.tsx +20 -0
- package/src/components/icons/countries/es.tsx +19 -0
- package/src/components/icons/countries/index.ts +3 -0
- package/src/components/icons/countries/us.tsx +21 -0
- package/src/components/icons/dataflow-03.tsx +15 -0
- package/src/components/icons/dotpoints-01.tsx +22 -0
- package/src/components/icons/dots-vertical.tsx +35 -0
- package/src/components/icons/download-03.tsx +16 -0
- package/src/components/icons/download-cloud-02.tsx +15 -0
- package/src/components/icons/drag.tsx +14 -0
- package/src/components/icons/dropper.tsx +21 -0
- package/src/components/icons/edit-01.tsx +15 -0
- package/src/components/icons/edit-02.tsx +9 -0
- package/src/components/icons/edit-03.tsx +23 -0
- package/src/components/icons/eye.tsx +22 -0
- package/src/components/icons/face-frown.tsx +15 -0
- package/src/components/icons/face-happy.tsx +15 -0
- package/src/components/icons/file-06.tsx +15 -0
- package/src/components/icons/file-attachment-04.tsx +15 -0
- package/src/components/icons/file-download-02.tsx +16 -0
- package/src/components/icons/file-plus-02.tsx +16 -0
- package/src/components/icons/file-search-01.tsx +22 -0
- package/src/components/icons/file-search-03.tsx +15 -0
- package/src/components/icons/filter-lines.tsx +21 -0
- package/src/components/icons/first-category.tsx +16 -0
- package/src/components/icons/first-stage.tsx +19 -0
- package/src/components/icons/folder.tsx +15 -0
- package/src/components/icons/google.tsx +12 -0
- package/src/components/icons/graduation-hat-02.tsx +15 -0
- package/src/components/icons/grid-01.tsx +36 -0
- package/src/components/icons/help-circle.tsx +16 -0
- package/src/components/icons/help-square.tsx +16 -0
- package/src/components/icons/home-line.tsx +21 -0
- package/src/components/icons/icons.stories.tsx +199 -0
- package/src/components/icons/index.ts +140 -0
- package/src/components/icons/info-circle.tsx +15 -0
- package/src/components/icons/italic-01.tsx +22 -0
- package/src/components/icons/last-category.tsx +11 -0
- package/src/components/icons/last-stage.tsx +19 -0
- package/src/components/icons/layout-alt-04.tsx +9 -0
- package/src/components/icons/lightbulb-02.tsx +16 -0
- package/src/components/icons/link-01.tsx +16 -0
- package/src/components/icons/link-broken-01.tsx +16 -0
- package/src/components/icons/linkedin-logo.tsx +17 -0
- package/src/components/icons/lock-01.tsx +21 -0
- package/src/components/icons/log-out-01.tsx +9 -0
- package/src/components/icons/mail-01.tsx +16 -0
- package/src/components/icons/marker-pin-02.tsx +10 -0
- package/src/components/icons/menu-01.tsx +9 -0
- package/src/components/icons/middle-category.tsx +10 -0
- package/src/components/icons/middle-stage.tsx +19 -0
- package/src/components/icons/ms-outlook.tsx +47 -0
- package/src/components/icons/paragraph-spacing.tsx +15 -0
- package/src/components/icons/phone-01.tsx +21 -0
- package/src/components/icons/pie-chart-02.tsx +22 -0
- package/src/components/icons/plus-circle.tsx +15 -0
- package/src/components/icons/portal-logo.tsx +76 -0
- package/src/components/icons/presentation-chart-02.tsx +14 -0
- package/src/components/icons/route.tsx +22 -0
- package/src/components/icons/save-01.tsx +15 -0
- package/src/components/icons/search-lg.tsx +15 -0
- package/src/components/icons/search-sm.tsx +9 -0
- package/src/components/icons/send-03.tsx +15 -0
- package/src/components/icons/settings-01.tsx +17 -0
- package/src/components/icons/settings-03.tsx +14 -0
- package/src/components/icons/share-05.tsx +15 -0
- package/src/components/icons/share-06.tsx +15 -0
- package/src/components/icons/slash-circle-01.tsx +9 -0
- package/src/components/icons/star-01.tsx +9 -0
- package/src/components/icons/step-icon-active.tsx +11 -0
- package/src/components/icons/step-icon-checked.tsx +10 -0
- package/src/components/icons/step-icon-default.tsx +11 -0
- package/src/components/icons/switch-horizontal-01.tsx +9 -0
- package/src/components/icons/table-01.tsx +15 -0
- package/src/components/icons/tag-01.tsx +15 -0
- package/src/components/icons/tag-03.tsx +15 -0
- package/src/components/icons/tool-02.tsx +14 -0
- package/src/components/icons/trash-01.tsx +15 -0
- package/src/components/icons/underline-01.tsx +22 -0
- package/src/components/icons/upload-cloud-02.tsx +15 -0
- package/src/components/icons/user-01.tsx +9 -0
- package/src/components/icons/user-03.tsx +9 -0
- package/src/components/icons/user-check-01.tsx +14 -0
- package/src/components/icons/user-circle.tsx +14 -0
- package/src/components/icons/user-edit.tsx +16 -0
- package/src/components/icons/user-minus-02.tsx +15 -0
- package/src/components/icons/user-plus-01.tsx +22 -0
- package/src/components/icons/user-plus-02.tsx +15 -0
- package/src/components/icons/user-square.tsx +16 -0
- package/src/components/icons/users-01.tsx +14 -0
- package/src/components/icons/users-plus-01.tsx +21 -0
- package/src/components/icons/users-plus.tsx +16 -0
- package/src/components/icons/vertical-drag.tsx +21 -0
- package/src/components/icons/x-circle.tsx +15 -0
- package/src/components/icons/x-close.tsx +9 -0
- package/src/components/icons/zap-fast.tsx +16 -0
- package/src/components/icons/zap.tsx +9 -0
- package/src/components/index.ts +4 -0
- package/src/components/molecules/Accordion/accordion.stories.tsx +81 -0
- package/src/components/molecules/Accordion/accordion.test.tsx +91 -0
- package/src/components/molecules/Accordion/accordion.tsx +65 -0
- package/src/components/molecules/Accordion/index.ts +1 -0
- package/src/components/molecules/Alert/alert.stories.tsx +75 -0
- package/src/components/molecules/Alert/alert.test.tsx +58 -0
- package/src/components/molecules/Alert/alert.tsx +67 -0
- package/src/components/molecules/Alert/index.ts +1 -0
- package/src/components/molecules/AlertDialog/alert-dialog.stories.tsx +55 -0
- package/src/components/molecules/AlertDialog/alert-dialog.test.tsx +34 -0
- package/src/components/molecules/AlertDialog/alert-dialog.tsx +172 -0
- package/src/components/molecules/AlertDialog/index.ts +1 -0
- package/src/components/molecules/Avatar/avatar.stories.tsx +98 -0
- package/src/components/molecules/Avatar/avatar.test.tsx +55 -0
- package/src/components/molecules/Avatar/avatar.tsx +55 -0
- package/src/components/molecules/Avatar/index.ts +1 -0
- package/src/components/molecules/Breadcrumb/breadcrumb.stories.tsx +125 -0
- package/src/components/molecules/Breadcrumb/breadcrumb.test.tsx +118 -0
- package/src/components/molecules/Breadcrumb/breadcrumb.tsx +120 -0
- package/src/components/molecules/Breadcrumb/index.ts +1 -0
- package/src/components/molecules/Card/card.stories.tsx +109 -0
- package/src/components/molecules/Card/card.test.tsx +103 -0
- package/src/components/molecules/Card/card.tsx +78 -0
- package/src/components/molecules/Card/index.ts +1 -0
- package/src/components/molecules/Collapsible/collapsible.stories.tsx +28 -0
- package/src/components/molecules/Collapsible/collapsible.test.tsx +36 -0
- package/src/components/molecules/Collapsible/collapsible.tsx +31 -0
- package/src/components/molecules/Collapsible/index.ts +1 -0
- package/src/components/molecules/ColorPicker/color-picker.stories.tsx +40 -0
- package/src/components/molecules/ColorPicker/color-picker.tsx +106 -0
- package/src/components/molecules/ColorPicker/index.ts +1 -0
- package/src/components/molecules/ColorScale/color-scale.stories.tsx +31 -0
- package/src/components/molecules/ColorScale/color-scale.tsx +74 -0
- package/src/components/molecules/ColorScale/index.ts +1 -0
- package/src/components/molecules/Command/command.stories.tsx +71 -0
- package/src/components/molecules/Command/command.test.tsx +50 -0
- package/src/components/molecules/Command/command.tsx +177 -0
- package/src/components/molecules/Command/index.ts +1 -0
- package/src/components/molecules/ContextMenu/context-menu.stories.tsx +69 -0
- package/src/components/molecules/ContextMenu/context-menu.test.tsx +25 -0
- package/src/components/molecules/ContextMenu/context-menu.tsx +259 -0
- package/src/components/molecules/ContextMenu/index.ts +1 -0
- package/src/components/molecules/DatePicker/date-picker.stories.tsx +204 -0
- package/src/components/molecules/DatePicker/date-picker.test.tsx +27 -0
- package/src/components/molecules/DatePicker/date-picker.tsx +486 -0
- package/src/components/molecules/DatePicker/index.ts +1 -0
- package/src/components/molecules/Dialog/dialog.stories.tsx +48 -0
- package/src/components/molecules/Dialog/dialog.test.tsx +51 -0
- package/src/components/molecules/Dialog/dialog.tsx +150 -0
- package/src/components/molecules/Dialog/index.ts +1 -0
- package/src/components/molecules/Drawer/drawer.stories.tsx +182 -0
- package/src/components/molecules/Drawer/drawer.test.tsx +100 -0
- package/src/components/molecules/Drawer/drawer.tsx +206 -0
- package/src/components/molecules/Drawer/index.ts +1 -0
- package/src/components/molecules/Dropdown/dropdown-async.stories.tsx +15 -0
- package/src/components/molecules/Dropdown/dropdown.stories.tsx +112 -0
- package/src/components/molecules/Dropdown/dropdown.test.tsx +128 -0
- package/src/components/molecules/Dropdown/dropdown.tsx +322 -0
- package/src/components/molecules/Dropdown/index.ts +1 -0
- package/src/components/molecules/DropdownMenu/dropdown-menu.stories.tsx +154 -0
- package/src/components/molecules/DropdownMenu/dropdown-menu.test.tsx +163 -0
- package/src/components/molecules/DropdownMenu/dropdown-menu.tsx +313 -0
- package/src/components/molecules/DropdownMenu/index.ts +1 -0
- package/src/components/molecules/HoverCard/hover-card.stories.tsx +48 -0
- package/src/components/molecules/HoverCard/hover-card.test.tsx +42 -0
- package/src/components/molecules/HoverCard/hover-card.tsx +44 -0
- package/src/components/molecules/HoverCard/index.ts +1 -0
- package/src/components/molecules/InputOTP/index.ts +1 -0
- package/src/components/molecules/InputOTP/input-otp.stories.tsx +52 -0
- package/src/components/molecules/InputOTP/input-otp.test.tsx +28 -0
- package/src/components/molecules/InputOTP/input-otp.tsx +76 -0
- package/src/components/molecules/Menubar/index.ts +1 -0
- package/src/components/molecules/Menubar/menubar.stories.tsx +113 -0
- package/src/components/molecules/Menubar/menubar.test.tsx +42 -0
- package/src/components/molecules/Menubar/menubar.tsx +314 -0
- package/src/components/molecules/NavigationMenu/index.ts +1 -0
- package/src/components/molecules/NavigationMenu/navigation-menu.stories.tsx +143 -0
- package/src/components/molecules/NavigationMenu/navigation-menu.test.tsx +69 -0
- package/src/components/molecules/NavigationMenu/navigation-menu.tsx +174 -0
- package/src/components/molecules/PDFViewer/index.ts +1 -0
- package/src/components/molecules/PDFViewer/pdf-viewer.stories.tsx +34 -0
- package/src/components/molecules/PDFViewer/pdf-viewer.test.tsx +26 -0
- package/src/components/molecules/PDFViewer/pdf-viewer.tsx +358 -0
- package/src/components/molecules/Pagination/index.ts +1 -0
- package/src/components/molecules/Pagination/pagination.stories.tsx +193 -0
- package/src/components/molecules/Pagination/pagination.test.tsx +448 -0
- package/src/components/molecules/Pagination/pagination.tsx +206 -0
- package/src/components/molecules/PaginationDotGroup/index.ts +1 -0
- package/src/components/molecules/PaginationDotGroup/pagination-dot-group.stories.tsx +211 -0
- package/src/components/molecules/PaginationDotGroup/pagination-dot-group.test.tsx +385 -0
- package/src/components/molecules/PaginationDotGroup/pagination-dot-group.tsx +119 -0
- package/src/components/molecules/Popover/index.ts +1 -0
- package/src/components/molecules/Popover/popover-menu.stories.tsx +27 -0
- package/src/components/molecules/Popover/popover.test.tsx +50 -0
- package/src/components/molecules/Popover/popover.tsx +38 -0
- package/src/components/molecules/ProgressSteps/index.ts +1 -0
- package/src/components/molecules/ProgressSteps/progress-steps.stories.tsx +36 -0
- package/src/components/molecules/ProgressSteps/progress-steps.test.tsx +470 -0
- package/src/components/molecules/ProgressSteps/progress-steps.tsx +140 -0
- package/src/components/molecules/RadioGroup/index.ts +1 -0
- package/src/components/molecules/RadioGroup/radio-group.stories.tsx +42 -0
- package/src/components/molecules/RadioGroup/radio-group.test.tsx +22 -0
- package/src/components/molecules/RadioGroup/radio-group.tsx +55 -0
- package/src/components/molecules/Resizable/index.ts +1 -0
- package/src/components/molecules/Resizable/resizable.stories.tsx +52 -0
- package/src/components/molecules/Resizable/resizable.test.tsx +22 -0
- package/src/components/molecules/Resizable/resizable.tsx +55 -0
- package/src/components/molecules/ScrollArea/index.ts +1 -0
- package/src/components/molecules/ScrollArea/scroll-area.stories.tsx +93 -0
- package/src/components/molecules/ScrollArea/scroll-area.test.tsx +28 -0
- package/src/components/molecules/ScrollArea/scroll-area.tsx +57 -0
- package/src/components/molecules/Select/index.ts +1 -0
- package/src/components/molecules/Select/select.stories.tsx +63 -0
- package/src/components/molecules/Select/select.test.tsx +80 -0
- package/src/components/molecules/Select/select.tsx +172 -0
- package/src/components/molecules/Sheet/index.ts +1 -0
- package/src/components/molecules/Sheet/sheet.stories.tsx +141 -0
- package/src/components/molecules/Sheet/sheet.test.tsx +70 -0
- package/src/components/molecules/Sheet/sheet.tsx +133 -0
- package/src/components/molecules/Tabs/index.ts +1 -0
- package/src/components/molecules/Tabs/tabs.stories.tsx +222 -0
- package/src/components/molecules/Tabs/tabs.test.tsx +113 -0
- package/src/components/molecules/Tabs/tabs.tsx +102 -0
- package/src/components/molecules/ToggleGroup/index.ts +1 -0
- package/src/components/molecules/ToggleGroup/toggle-group.stories.tsx +117 -0
- package/src/components/molecules/ToggleGroup/toggle-group.test.tsx +100 -0
- package/src/components/molecules/ToggleGroup/toggle-group.tsx +70 -0
- package/src/components/molecules/Tooltip/index.ts +1 -0
- package/src/components/molecules/Tooltip/tooltip.stories.tsx +133 -0
- package/src/components/molecules/Tooltip/tooltip.test.tsx +58 -0
- package/src/components/molecules/Tooltip/tooltip.tsx +58 -0
- package/src/components/molecules/index.ts +33 -0
- package/src/components/organisms/Carousel/carousel.stories.tsx +94 -0
- package/src/components/organisms/Carousel/carousel.test.tsx +24 -0
- package/src/components/organisms/Carousel/carousel.tsx +383 -0
- package/src/components/organisms/Carousel/index.ts +1 -0
- package/src/components/organisms/Chart/chart.stories.tsx +102 -0
- package/src/components/organisms/Chart/chart.test.tsx +105 -0
- package/src/components/organisms/Chart/chart.tsx +294 -0
- package/src/components/organisms/Chart/index.ts +1 -0
- package/src/components/organisms/FileUpload/FilePreview/file-preview.tsx +55 -0
- package/src/components/organisms/FileUpload/FilePreview/index.ts +1 -0
- package/src/components/organisms/FileUpload/file-upload.stories.tsx +20 -0
- package/src/components/organisms/FileUpload/file-upload.test.tsx +59 -0
- package/src/components/organisms/FileUpload/file-upload.tsx +175 -0
- package/src/components/organisms/FileUpload/file.d.ts +21 -0
- package/src/components/organisms/FileUpload/index.ts +1 -0
- package/src/components/organisms/Form/form.stories.tsx +155 -0
- package/src/components/organisms/Form/form.test.tsx +49 -0
- package/src/components/organisms/Form/form.tsx +133 -0
- package/src/components/organisms/Form/index.ts +1 -0
- package/src/components/organisms/Sidebar/index.ts +1 -0
- package/src/components/organisms/Sidebar/sidebar.stories.tsx +86 -0
- package/src/components/organisms/Sidebar/sidebar.test.tsx +101 -0
- package/src/components/organisms/Sidebar/sidebar.tsx +666 -0
- package/src/components/organisms/Table/index.ts +1 -0
- package/src/components/organisms/Table/table.stories.tsx +86 -0
- package/src/components/organisms/Table/table.test.tsx +42 -0
- package/src/components/organisms/Table/table.tsx +120 -0
- package/src/components/organisms/index.ts +6 -0
- package/src/constants/brazilian-states.ts +29 -0
- package/src/constants/index.ts +1 -0
- package/src/hooks/index.ts +10 -0
- package/src/hooks/useEditorActiveMarks.ts +63 -0
- package/src/hooks/useForm.ts +8 -0
- package/src/hooks/useFormContext.ts +7 -0
- package/src/hooks/useFormField.ts +41 -0
- package/src/hooks/useMobile.ts +61 -0
- package/src/hooks/useOnToggle.ts +28 -0
- package/src/hooks/usePDFNavigation.ts +41 -0
- package/src/hooks/usePDFZoom.ts +35 -0
- package/src/hooks/useSidebar.ts +23 -0
- package/src/hooks/useToast.tsx +63 -0
- package/src/index.css +73 -0
- package/src/main.ts +6 -0
- package/src/theme.css +388 -0
- package/src/utils/api/api.test.ts +64 -0
- package/src/utils/api/api.ts +34 -0
- package/src/utils/api/index.ts +1 -0
- package/src/utils/array/array.test.ts +160 -0
- package/src/utils/array/array.ts +43 -0
- package/src/utils/array/index.ts +1 -0
- package/src/utils/clipboard/clipboard.test.ts +218 -0
- package/src/utils/clipboard/clipboard.ts +40 -0
- package/src/utils/clipboard/index.ts +1 -0
- package/src/utils/cn/cn.test.ts +43 -0
- package/src/utils/cn/cn.ts +6 -0
- package/src/utils/cn/index.ts +1 -0
- package/src/utils/color-utils/color-utils.test.ts +46 -0
- package/src/utils/color-utils/color-utils.ts +97 -0
- package/src/utils/color-utils/index.ts +1 -0
- package/src/utils/countries/countries.ts +69 -0
- package/src/utils/countries/index.ts +1 -0
- package/src/utils/currency/currency.test.ts +114 -0
- package/src/utils/currency/currency.ts +134 -0
- package/src/utils/currency/index.ts +1 -0
- package/src/utils/date/date.test.ts +167 -0
- package/src/utils/date/date.ts +83 -0
- package/src/utils/date/index.ts +1 -0
- package/src/utils/file/file.ts +45 -0
- package/src/utils/file/index.ts +1 -0
- package/src/utils/get-initials/get-initials.test.ts +40 -0
- package/src/utils/get-initials/get-initials.ts +13 -0
- package/src/utils/get-initials/index.ts +1 -0
- package/src/utils/index.ts +14 -0
- package/src/utils/masks/index.ts +1 -0
- package/src/utils/masks/masks.ts +180 -0
- package/src/utils/render-highlighted-text/index.ts +1 -0
- package/src/utils/render-highlighted-text/render-highlighted-text.tsx +25 -0
- package/src/utils/string/index.ts +1 -0
- package/src/utils/string/string.test.ts +171 -0
- package/src/utils/string/string.ts +155 -0
- package/src/utils/video/index.ts +1 -0
- package/src/utils/video/video.ts +9 -0
- package/src/vite-env.d.ts +3 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { Textarea } from './textarea';
|
|
4
|
+
|
|
5
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Textarea> = {
|
|
8
|
+
title: 'Components/Data Entry/Textarea',
|
|
9
|
+
component: Textarea,
|
|
10
|
+
tags: [ 'autodocs' ],
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component:
|
|
15
|
+
'Accessible and styled textarea component with Tailwind CSS. Supports visual states like focus, error, disabled, and filled. Ideal for multiline text fields in forms.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
controls: { expanded: true },
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
'className': {
|
|
22
|
+
control: 'text',
|
|
23
|
+
description: 'Additional Tailwind utility classes for styling.',
|
|
24
|
+
table: {
|
|
25
|
+
category: 'Style',
|
|
26
|
+
type: { summary: 'string' },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
'placeholder': {
|
|
30
|
+
control: 'text',
|
|
31
|
+
description: 'Text displayed when the textarea is empty.',
|
|
32
|
+
table: {
|
|
33
|
+
category: 'Content',
|
|
34
|
+
type: { summary: 'string' },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
'disabled': {
|
|
38
|
+
control: 'boolean',
|
|
39
|
+
description: 'Disables the textarea, preventing editing.',
|
|
40
|
+
table: {
|
|
41
|
+
category: 'Behavior',
|
|
42
|
+
type: { summary: 'boolean' },
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
'value': {
|
|
46
|
+
control: 'text',
|
|
47
|
+
description: 'Controlled value of the textarea.',
|
|
48
|
+
table: {
|
|
49
|
+
category: 'State',
|
|
50
|
+
type: { summary: 'string' },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
'defaultValue': {
|
|
54
|
+
control: 'text',
|
|
55
|
+
description: 'Initial value of the textarea in uncontrolled mode.',
|
|
56
|
+
table: {
|
|
57
|
+
category: 'State',
|
|
58
|
+
type: { summary: 'string' },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
'required': {
|
|
62
|
+
control: 'boolean',
|
|
63
|
+
description: 'Marks the field as required.',
|
|
64
|
+
table: {
|
|
65
|
+
category: 'Validation',
|
|
66
|
+
type: { summary: 'boolean' },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
'aria-invalid': {
|
|
70
|
+
control: 'boolean',
|
|
71
|
+
description: 'Defines the visual and semantic error state.',
|
|
72
|
+
table: {
|
|
73
|
+
category: 'Accessibility',
|
|
74
|
+
type: { summary: 'boolean' },
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
'onChange': {
|
|
78
|
+
action: 'changed',
|
|
79
|
+
description: 'Callback triggered when typing in the textarea.',
|
|
80
|
+
table: {
|
|
81
|
+
category: 'Events',
|
|
82
|
+
type: { summary: '(event: React.ChangeEvent<HTMLTextAreaElement>) => void' },
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default meta;
|
|
89
|
+
type Story = StoryObj<typeof Textarea>;
|
|
90
|
+
|
|
91
|
+
export const Controlled: Story = {
|
|
92
|
+
render: args => {
|
|
93
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
94
|
+
const [ value, setValue ] = React.useState('');
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div className="flex flex-col space-y-2">
|
|
98
|
+
<Textarea
|
|
99
|
+
{...args}
|
|
100
|
+
value={value}
|
|
101
|
+
onChange={e => setValue(e.target.value)}
|
|
102
|
+
placeholder="Type something..."
|
|
103
|
+
/>
|
|
104
|
+
<span className="text-sm text-muted-foreground">Current value: {value}</span>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
parameters: {
|
|
109
|
+
docs: {
|
|
110
|
+
description: {
|
|
111
|
+
story: 'Example of a textarea controlled by local state.',
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const Default: Story = {
|
|
118
|
+
args: {
|
|
119
|
+
placeholder: 'Type your message here...',
|
|
120
|
+
},
|
|
121
|
+
parameters: {
|
|
122
|
+
docs: {
|
|
123
|
+
description: {
|
|
124
|
+
story: 'Basic textarea with placeholder.',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const Disabled: Story = {
|
|
131
|
+
args: {
|
|
132
|
+
disabled: true,
|
|
133
|
+
defaultValue: 'Campo desabilitado.',
|
|
134
|
+
},
|
|
135
|
+
parameters: {
|
|
136
|
+
docs: {
|
|
137
|
+
description: {
|
|
138
|
+
story: 'Disabled textarea for data entry.',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const Filled: Story = {
|
|
145
|
+
args: {
|
|
146
|
+
defaultValue: 'Text already filled.',
|
|
147
|
+
},
|
|
148
|
+
parameters: {
|
|
149
|
+
docs: {
|
|
150
|
+
description: {
|
|
151
|
+
story: 'Textarea already filled with initial value.',
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export const Invalid: Story = {
|
|
158
|
+
args: {
|
|
159
|
+
'aria-invalid': true,
|
|
160
|
+
'defaultValue': 'Invalid text',
|
|
161
|
+
},
|
|
162
|
+
parameters: {
|
|
163
|
+
docs: {
|
|
164
|
+
description: {
|
|
165
|
+
story: 'Displays the error state with appropriate visual styles.',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { Textarea } from './textarea';
|
|
5
|
+
|
|
6
|
+
describe('<Textarea />', () => {
|
|
7
|
+
it('renders the textarea correctly', () => {
|
|
8
|
+
render(<Textarea aria-label="Comment" />);
|
|
9
|
+
const textarea = screen.getByLabelText('Comment');
|
|
10
|
+
expect(textarea).toBeInTheDocument();
|
|
11
|
+
expect(textarea.tagName).toBe('TEXTAREA');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('applies custom className in addition to default styles', () => {
|
|
15
|
+
render(<Textarea aria-label="Styled" className="custom-class" />);
|
|
16
|
+
const textarea = screen.getByLabelText('Styled');
|
|
17
|
+
expect(textarea).toHaveClass('custom-class');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('calls onChange handler when value changes', () => {
|
|
21
|
+
const handleChange = vi.fn();
|
|
22
|
+
render(<Textarea aria-label="Description" onChange={handleChange} />);
|
|
23
|
+
const textarea = screen.getByLabelText('Description');
|
|
24
|
+
fireEvent.change(textarea, { target: { value: 'New text' } });
|
|
25
|
+
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('is disabled when the disabled prop is passed', () => {
|
|
29
|
+
render(<Textarea aria-label="Disabled" disabled />);
|
|
30
|
+
const textarea = screen.getByLabelText('Disabled');
|
|
31
|
+
expect(textarea).toBeDisabled();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('sets aria-invalid when provided', () => {
|
|
35
|
+
render(<Textarea aria-label="Invalid input" aria-invalid="true" />);
|
|
36
|
+
const textarea = screen.getByLabelText('Invalid input');
|
|
37
|
+
expect(textarea).toHaveAttribute('aria-invalid', 'true');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('can be found using the data-slot attribute', () => {
|
|
41
|
+
render(<Textarea aria-label="Slot test" />);
|
|
42
|
+
const textarea = screen.getByLabelText('Slot test');
|
|
43
|
+
expect(textarea).toHaveAttribute('data-slot', 'textarea');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('accepts and renders placeholder text', () => {
|
|
47
|
+
render(<Textarea aria-label="Bio" placeholder="Enter your bio" />);
|
|
48
|
+
const textarea = screen.getByPlaceholderText('Enter your bio');
|
|
49
|
+
expect(textarea).toBeInTheDocument();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should match snapshot', () => {
|
|
53
|
+
const { container } = render(<Textarea />);
|
|
54
|
+
expect(container).toMatchSnapshot();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { cn } from '@/utils';
|
|
4
|
+
|
|
5
|
+
function Textarea ({ className, ...props }: React.ComponentProps<'textarea'>) {
|
|
6
|
+
return (
|
|
7
|
+
<textarea
|
|
8
|
+
data-slot="textarea"
|
|
9
|
+
className={cn(
|
|
10
|
+
'rounded-2xl bg-white border border-gray-300 focus-visible-primary',
|
|
11
|
+
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
12
|
+
'flex field-sizing-content',
|
|
13
|
+
'placeholder:text-gray-500 placeholder:text-base text-base',
|
|
14
|
+
'min-h-16 w-full',
|
|
15
|
+
'px-3 py-2',
|
|
16
|
+
'transition-[color,box-shadow]',
|
|
17
|
+
'outline-none',
|
|
18
|
+
className
|
|
19
|
+
)}
|
|
20
|
+
maxLength={props.maxLength ?? 1000}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { Textarea };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './toggle';
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { Bold } from 'lucide-react';
|
|
5
|
+
|
|
6
|
+
import { Toggle } from './toggle';
|
|
7
|
+
|
|
8
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof Toggle> = {
|
|
11
|
+
title: 'Components/Data Entry/Toggle',
|
|
12
|
+
component: Toggle,
|
|
13
|
+
tags: [ 'autodocs' ],
|
|
14
|
+
parameters: {
|
|
15
|
+
docs: {
|
|
16
|
+
description: {
|
|
17
|
+
component:
|
|
18
|
+
'Toggle button based on Radix UI Toggle. Supports style variants, sizes, controlled state, and icons. Ideal for actions like bold, italic, or any binary state control.',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
controls: { expanded: true },
|
|
22
|
+
},
|
|
23
|
+
argTypes: {
|
|
24
|
+
'variant': {
|
|
25
|
+
control: 'radio',
|
|
26
|
+
options: [ 'default', 'outline' ],
|
|
27
|
+
description: 'Visual style of the button.',
|
|
28
|
+
table: {
|
|
29
|
+
category: 'Style',
|
|
30
|
+
type: { summary: '"default" | "outline"' },
|
|
31
|
+
defaultValue: { summary: 'default' },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
'size': {
|
|
35
|
+
control: 'radio',
|
|
36
|
+
options: [ 'default', 'sm', 'lg' ],
|
|
37
|
+
description: 'Button size.',
|
|
38
|
+
table: {
|
|
39
|
+
category: 'Size',
|
|
40
|
+
type: { summary: '"default" | "sm" | "lg"' },
|
|
41
|
+
defaultValue: { summary: 'default' },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
'pressed': {
|
|
45
|
+
control: 'boolean',
|
|
46
|
+
description: 'Controls the pressed state of the button.',
|
|
47
|
+
table: {
|
|
48
|
+
category: 'State',
|
|
49
|
+
type: { summary: 'boolean' },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
'defaultPressed': {
|
|
53
|
+
control: 'boolean',
|
|
54
|
+
description: 'Defines the initial state of the button (uncontrolled mode).',
|
|
55
|
+
table: {
|
|
56
|
+
category: 'State',
|
|
57
|
+
type: { summary: 'boolean' },
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
'disabled': {
|
|
61
|
+
control: 'boolean',
|
|
62
|
+
description: 'Disables button interaction.',
|
|
63
|
+
table: {
|
|
64
|
+
category: 'Behavior',
|
|
65
|
+
type: { summary: 'boolean' },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
'aria-invalid': {
|
|
69
|
+
control: 'boolean',
|
|
70
|
+
description: 'Applies visual and semantic error styles.',
|
|
71
|
+
table: {
|
|
72
|
+
category: 'Accessibility',
|
|
73
|
+
type: { summary: 'boolean' },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
'onPressedChange': {
|
|
77
|
+
action: 'pressed changed',
|
|
78
|
+
description: 'Triggered when the button is activated or deactivated.',
|
|
79
|
+
table: {
|
|
80
|
+
category: 'Events',
|
|
81
|
+
type: {
|
|
82
|
+
summary: '(pressed: boolean) => void',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export default meta;
|
|
90
|
+
type Story = StoryObj<typeof Toggle>;
|
|
91
|
+
|
|
92
|
+
export const Controlled: Story = {
|
|
93
|
+
render: args => {
|
|
94
|
+
const [ pressed, setPressed ] = React.useState(false);
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<Toggle {...args} pressed={pressed} onPressedChange={setPressed}>
|
|
98
|
+
{pressed ? 'Activated' : 'Deactivated'}
|
|
99
|
+
</Toggle>
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
parameters: {
|
|
103
|
+
docs: {
|
|
104
|
+
description: {
|
|
105
|
+
story: 'Controlled example with external state.',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const Default: Story = {
|
|
112
|
+
args: {
|
|
113
|
+
children: 'Default toggle',
|
|
114
|
+
defaultPressed: false,
|
|
115
|
+
},
|
|
116
|
+
parameters: {
|
|
117
|
+
docs: {
|
|
118
|
+
description: {
|
|
119
|
+
story: 'Basic toggle with default style.',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const Outline: Story = {
|
|
126
|
+
args: {
|
|
127
|
+
children: 'Toggle with border',
|
|
128
|
+
variant: 'outline',
|
|
129
|
+
defaultPressed: true,
|
|
130
|
+
},
|
|
131
|
+
parameters: {
|
|
132
|
+
docs: {
|
|
133
|
+
description: {
|
|
134
|
+
story: 'Toggle with "outline" style, more visible on light backgrounds.',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const Sizes: Story = {
|
|
141
|
+
render: () => (
|
|
142
|
+
<div className="flex items-center gap-4">
|
|
143
|
+
<Toggle size="sm">Small</Toggle>
|
|
144
|
+
<Toggle size="default">Medium</Toggle>
|
|
145
|
+
<Toggle size="lg">Large</Toggle>
|
|
146
|
+
</div>
|
|
147
|
+
),
|
|
148
|
+
parameters: {
|
|
149
|
+
docs: {
|
|
150
|
+
description: {
|
|
151
|
+
story: 'Demonstrates the three available button sizes.',
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export const WithIcon: Story = {
|
|
158
|
+
args: {
|
|
159
|
+
children: <Bold />,
|
|
160
|
+
defaultPressed: false,
|
|
161
|
+
},
|
|
162
|
+
parameters: {
|
|
163
|
+
docs: {
|
|
164
|
+
description: {
|
|
165
|
+
story:
|
|
166
|
+
'Toggle with icon. Ideal for text editors and formatting tools.',
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { Toggle } from './toggle';
|
|
5
|
+
|
|
6
|
+
describe('<Toggle />', () => {
|
|
7
|
+
it('renders the toggle button with default variant and size', () => {
|
|
8
|
+
render(<Toggle aria-label="Toggle theme" />);
|
|
9
|
+
const toggle = screen.getByLabelText('Toggle theme');
|
|
10
|
+
expect(toggle).toBeInTheDocument();
|
|
11
|
+
expect(toggle).toHaveAttribute('aria-pressed', 'false');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('applies custom className along with variant styles', () => {
|
|
15
|
+
render(<Toggle aria-label="Custom Toggle" className="custom-class" />);
|
|
16
|
+
const toggle = screen.getByLabelText('Custom Toggle');
|
|
17
|
+
expect(toggle).toHaveClass('custom-class');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('respects the `variant` and `size` props', () => {
|
|
21
|
+
render(<Toggle aria-label="Styled Toggle" variant="outline" size="sm" />);
|
|
22
|
+
const toggle = screen.getByLabelText('Styled Toggle');
|
|
23
|
+
expect(toggle.className).toMatch(/border/); // outline has border
|
|
24
|
+
expect(toggle.className).toMatch(/h-8/); // sm has h-8
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('toggles aria-pressed on click', () => {
|
|
28
|
+
render(<Toggle aria-label="Toggle status" />);
|
|
29
|
+
const toggle = screen.getByLabelText('Toggle status');
|
|
30
|
+
expect(toggle).toHaveAttribute('aria-pressed', 'false');
|
|
31
|
+
fireEvent.click(toggle);
|
|
32
|
+
expect(toggle).toHaveAttribute('aria-pressed', 'true');
|
|
33
|
+
fireEvent.click(toggle);
|
|
34
|
+
expect(toggle).toHaveAttribute('aria-pressed', 'false');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('does not toggle when disabled', () => {
|
|
38
|
+
render(<Toggle aria-label="Disabled toggle" disabled />);
|
|
39
|
+
const toggle = screen.getByLabelText('Disabled toggle');
|
|
40
|
+
expect(toggle).toBeDisabled();
|
|
41
|
+
expect(toggle).toHaveAttribute('aria-pressed', 'false');
|
|
42
|
+
fireEvent.click(toggle);
|
|
43
|
+
expect(toggle).toHaveAttribute('aria-pressed', 'false'); // still false
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('sets aria-invalid when passed', () => {
|
|
47
|
+
render(<Toggle aria-label="Invalid toggle" aria-invalid="true" />);
|
|
48
|
+
const toggle = screen.getByLabelText('Invalid toggle');
|
|
49
|
+
expect(toggle).toHaveAttribute('aria-invalid', 'true');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('is accessible via data-slot attribute', () => {
|
|
53
|
+
render(<Toggle aria-label="Slot test" />);
|
|
54
|
+
const toggle = screen.getByLabelText('Slot test');
|
|
55
|
+
expect(toggle).toHaveAttribute('data-slot', 'toggle');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should match snapshot', () => {
|
|
59
|
+
const { container } = render(<Toggle />);
|
|
60
|
+
expect(container).toMatchSnapshot();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* eslint-disable react-refresh/only-export-components */
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
5
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
6
|
+
|
|
7
|
+
import { cn } from '@/utils';
|
|
8
|
+
|
|
9
|
+
const toggleVariants = cva(
|
|
10
|
+
'inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*=\'size-\'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap',
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default: 'bg-transparent',
|
|
15
|
+
outline:
|
|
16
|
+
'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
default: 'h-9 px-2 min-w-9',
|
|
20
|
+
sm: 'h-8 px-1.5 min-w-8',
|
|
21
|
+
lg: 'h-10 px-2.5 min-w-10',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
variant: 'default',
|
|
26
|
+
size: 'default',
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
function Toggle ({
|
|
32
|
+
className,
|
|
33
|
+
variant,
|
|
34
|
+
size,
|
|
35
|
+
...props
|
|
36
|
+
}: React.ComponentProps<typeof TogglePrimitive.Root> &
|
|
37
|
+
VariantProps<typeof toggleVariants>) {
|
|
38
|
+
return (
|
|
39
|
+
<TogglePrimitive.Root
|
|
40
|
+
data-slot="toggle"
|
|
41
|
+
className={cn(toggleVariants({ variant, size, className }))}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { Toggle, toggleVariants };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './typography';
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Typography } from './typography';
|
|
2
|
+
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Typography> = {
|
|
6
|
+
title: 'Components/Data Display/Typography',
|
|
7
|
+
component: Typography,
|
|
8
|
+
tags: [ 'autodocs' ],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'Reusable typography component with support for different variants like title, paragraph, and auxiliary text.',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
controls: { expanded: true },
|
|
17
|
+
},
|
|
18
|
+
argTypes: {
|
|
19
|
+
variant: {
|
|
20
|
+
control: 'select',
|
|
21
|
+
options: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'lead', 'paragraph', 'small' ],
|
|
22
|
+
description: 'Defines the typographic style.',
|
|
23
|
+
table: {
|
|
24
|
+
type: { summary: 'h1 | h2 | h3 | h4 | h5 | h6 | lead | paragraph | small' },
|
|
25
|
+
defaultValue: { summary: 'paragraph' },
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
as: {
|
|
29
|
+
control: 'text',
|
|
30
|
+
description: 'Overwrites the default HTML element used.',
|
|
31
|
+
table: {
|
|
32
|
+
type: { summary: 'React.ElementType' },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
className: {
|
|
36
|
+
control: 'text',
|
|
37
|
+
description: 'Additional TailwindCSS classes for styling.',
|
|
38
|
+
},
|
|
39
|
+
children: {
|
|
40
|
+
control: 'text',
|
|
41
|
+
description: 'Text content displayed in the component.',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
args: {
|
|
45
|
+
children: 'Example text for the Typography component',
|
|
46
|
+
variant: 'paragraph',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default meta;
|
|
51
|
+
type Story = StoryObj<typeof meta>;
|
|
52
|
+
|
|
53
|
+
export const Heading1: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
variant: 'h1',
|
|
56
|
+
children: 'Main H1 Title',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const Heading2: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
variant: 'h2',
|
|
63
|
+
children: 'Subtitle H2',
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const Lead: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
variant: 'lead',
|
|
70
|
+
children: 'Intermediate highlighted text.',
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const Paragraph: Story = {
|
|
75
|
+
args: {
|
|
76
|
+
variant: 'paragraph',
|
|
77
|
+
children: 'This is an example paragraph explaining something in more detail.',
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const SmallText: Story = {
|
|
82
|
+
args: {
|
|
83
|
+
variant: 'small',
|
|
84
|
+
children: 'Small text for observations or captions.',
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const WithCustomElement: Story = {
|
|
89
|
+
args: {
|
|
90
|
+
variant: 'h3',
|
|
91
|
+
as: 'label',
|
|
92
|
+
children: 'Label for input',
|
|
93
|
+
className: 'text-red-500',
|
|
94
|
+
},
|
|
95
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { Typography } from './typography';
|
|
5
|
+
|
|
6
|
+
describe('<Typography />', () => {
|
|
7
|
+
it('renders with default variant (paragraph)', () => {
|
|
8
|
+
render(<Typography>Default text</Typography>);
|
|
9
|
+
const element = screen.getByText('Default text');
|
|
10
|
+
expect(element.tagName.toLowerCase()).toBe('p');
|
|
11
|
+
expect(element).toHaveClass('text-base');
|
|
12
|
+
expect(element).toHaveAttribute('data-slot', 'typography');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('renders with specific variant: h2', () => {
|
|
16
|
+
render(<Typography variant="h2">Heading Level 2</Typography>);
|
|
17
|
+
const element = screen.getByText('Heading Level 2');
|
|
18
|
+
expect(element.tagName.toLowerCase()).toBe('h2');
|
|
19
|
+
expect(element).toHaveClass('text-4xl');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('renders with variant "small" using default tag <span>', () => {
|
|
23
|
+
render(<Typography variant="small">Small text</Typography>);
|
|
24
|
+
const element = screen.getByText('Small text');
|
|
25
|
+
expect(element.tagName.toLowerCase()).toBe('span');
|
|
26
|
+
expect(element).toHaveClass('text-sm');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('overrides default tag using `as` prop', () => {
|
|
30
|
+
render(
|
|
31
|
+
<Typography variant="h3" as="div">
|
|
32
|
+
Custom tag with h3 variant
|
|
33
|
+
</Typography>
|
|
34
|
+
);
|
|
35
|
+
const element = screen.getByText('Custom tag with h3 variant');
|
|
36
|
+
expect(element.tagName.toLowerCase()).toBe('div');
|
|
37
|
+
expect(element).toHaveClass('text-3xl');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('applies custom className along with variant classes', () => {
|
|
41
|
+
render(
|
|
42
|
+
<Typography variant="lead" className="custom-class">
|
|
43
|
+
Custom class test
|
|
44
|
+
</Typography>
|
|
45
|
+
);
|
|
46
|
+
const element = screen.getByText('Custom class test');
|
|
47
|
+
expect(element).toHaveClass('custom-class');
|
|
48
|
+
expect(element).toHaveClass('text-xl');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('passes through additional props', () => {
|
|
52
|
+
render(
|
|
53
|
+
<Typography variant="h4" id="heading-id" aria-label="Heading Label">
|
|
54
|
+
Extra props test
|
|
55
|
+
</Typography>
|
|
56
|
+
);
|
|
57
|
+
const element = screen.getByText('Extra props test');
|
|
58
|
+
expect(element).toHaveAttribute('id', 'heading-id');
|
|
59
|
+
expect(element).toHaveAttribute('aria-label', 'Heading Label');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should match snapshot', () => {
|
|
63
|
+
const { container } = render(<Typography>Text</Typography>);
|
|
64
|
+
expect(container).toMatchSnapshot();
|
|
65
|
+
});
|
|
66
|
+
});
|