@regardio/react 0.3.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/LICENSE +9 -0
- package/README.md +133 -0
- package/dist/components/background-slideshow.d.ts +22 -0
- package/dist/components/background-slideshow.d.ts.map +1 -0
- package/dist/components/background-slideshow.js +76 -0
- package/dist/components/blurry-gradient.d.ts +9 -0
- package/dist/components/blurry-gradient.d.ts.map +1 -0
- package/dist/components/blurry-gradient.js +6 -0
- package/dist/components/box.d.ts +17 -0
- package/dist/components/box.d.ts.map +1 -0
- package/dist/components/box.js +25 -0
- package/dist/components/carousel.d.ts +26 -0
- package/dist/components/carousel.d.ts.map +1 -0
- package/dist/components/carousel.js +87 -0
- package/dist/components/countdown.d.ts +2 -0
- package/dist/components/countdown.d.ts.map +1 -0
- package/dist/components/countdown.js +48 -0
- package/dist/components/definition-list.d.ts +40 -0
- package/dist/components/definition-list.d.ts.map +1 -0
- package/dist/components/definition-list.js +57 -0
- package/dist/components/generic-error.d.ts +23 -0
- package/dist/components/generic-error.d.ts.map +1 -0
- package/dist/components/generic-error.js +39 -0
- package/dist/components/heading.d.ts +24 -0
- package/dist/components/heading.d.ts.map +1 -0
- package/dist/components/heading.js +29 -0
- package/dist/components/highlight.d.ts +16 -0
- package/dist/components/highlight.d.ts.map +1 -0
- package/dist/components/highlight.js +19 -0
- package/dist/components/icon-button.d.ts +6 -0
- package/dist/components/icon-button.d.ts.map +1 -0
- package/dist/components/icon-button.js +6 -0
- package/dist/components/if.d.ts +8 -0
- package/dist/components/if.d.ts.map +1 -0
- package/dist/components/if.js +16 -0
- package/dist/components/iframe.d.ts +8 -0
- package/dist/components/iframe.d.ts.map +1 -0
- package/dist/components/iframe.js +3 -0
- package/dist/components/item.d.ts +67 -0
- package/dist/components/item.d.ts.map +1 -0
- package/dist/components/item.js +309 -0
- package/dist/components/leaflet-map.d.ts +33 -0
- package/dist/components/leaflet-map.d.ts.map +1 -0
- package/dist/components/leaflet-map.js +195 -0
- package/dist/components/link.d.ts +41 -0
- package/dist/components/link.d.ts.map +1 -0
- package/dist/components/link.js +111 -0
- package/dist/components/link.test.d.ts +2 -0
- package/dist/components/link.test.d.ts.map +1 -0
- package/dist/components/link.test.js +204 -0
- package/dist/components/list-item.d.ts +16 -0
- package/dist/components/list-item.d.ts.map +1 -0
- package/dist/components/list-item.js +19 -0
- package/dist/components/maptiler-map.d.ts +26 -0
- package/dist/components/maptiler-map.d.ts.map +1 -0
- package/dist/components/maptiler-map.js +116 -0
- package/dist/components/markdown-container.d.ts +20 -0
- package/dist/components/markdown-container.d.ts.map +1 -0
- package/dist/components/markdown-container.js +93 -0
- package/dist/components/password-input.d.ts +9 -0
- package/dist/components/password-input.d.ts.map +1 -0
- package/dist/components/password-input.js +13 -0
- package/dist/components/picture.d.ts +26 -0
- package/dist/components/picture.d.ts.map +1 -0
- package/dist/components/picture.js +36 -0
- package/dist/components/protected-email.d.ts +9 -0
- package/dist/components/protected-email.d.ts.map +1 -0
- package/dist/components/protected-email.js +16 -0
- package/dist/components/text.d.ts +17 -0
- package/dist/components/text.d.ts.map +1 -0
- package/dist/components/text.js +27 -0
- package/dist/components/unordered-list.d.ts +16 -0
- package/dist/components/unordered-list.d.ts.map +1 -0
- package/dist/components/unordered-list.js +21 -0
- package/dist/hooks/use-current-route-data.d.ts +2 -0
- package/dist/hooks/use-current-route-data.d.ts.map +1 -0
- package/dist/hooks/use-current-route-data.js +12 -0
- package/dist/hooks/use-focus-search.d.ts +3 -0
- package/dist/hooks/use-focus-search.d.ts.map +1 -0
- package/dist/hooks/use-focus-search.js +15 -0
- package/dist/hooks/use-matches-data.d.ts +2 -0
- package/dist/hooks/use-matches-data.d.ts.map +1 -0
- package/dist/hooks/use-matches-data.js +11 -0
- package/dist/hooks/use-media-query.d.ts +2 -0
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +16 -0
- package/dist/hooks/use-mobile.d.ts +2 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-mobile.js +15 -0
- package/dist/hooks/use-nonce.d.ts +5 -0
- package/dist/hooks/use-nonce.d.ts.map +1 -0
- package/dist/hooks/use-nonce.js +9 -0
- package/dist/hooks/use-nonce.test.d.ts +2 -0
- package/dist/hooks/use-nonce.test.d.ts.map +1 -0
- package/dist/hooks/use-nonce.test.js +27 -0
- package/dist/hooks/use-orientation.d.ts +3 -0
- package/dist/hooks/use-orientation.d.ts.map +1 -0
- package/dist/hooks/use-orientation.js +25 -0
- package/dist/hooks/use-user.d.ts +15 -0
- package/dist/hooks/use-user.d.ts.map +1 -0
- package/dist/hooks/use-user.js +17 -0
- package/dist/shadcn/accordion.d.ts +25 -0
- package/dist/shadcn/accordion.d.ts.map +1 -0
- package/dist/shadcn/accordion.js +45 -0
- package/dist/shadcn/alert-dialog.d.ts +73 -0
- package/dist/shadcn/alert-dialog.d.ts.map +1 -0
- package/dist/shadcn/alert-dialog.js +93 -0
- package/dist/shadcn/alert.d.ts +34 -0
- package/dist/shadcn/alert.d.ts.map +1 -0
- package/dist/shadcn/alert.js +42 -0
- package/dist/shadcn/aspect-ratio.d.ts +6 -0
- package/dist/shadcn/aspect-ratio.d.ts.map +1 -0
- package/dist/shadcn/aspect-ratio.js +7 -0
- package/dist/shadcn/avatar.d.ts +16 -0
- package/dist/shadcn/avatar.d.ts.map +1 -0
- package/dist/shadcn/avatar.js +27 -0
- package/dist/shadcn/badge.d.ts +29 -0
- package/dist/shadcn/badge.d.ts.map +1 -0
- package/dist/shadcn/badge.js +29 -0
- package/dist/shadcn/breadcrumb.d.ts +42 -0
- package/dist/shadcn/breadcrumb.d.ts.map +1 -0
- package/dist/shadcn/breadcrumb.js +74 -0
- package/dist/shadcn/button.d.ts +38 -0
- package/dist/shadcn/button.d.ts.map +1 -0
- package/dist/shadcn/button.js +38 -0
- package/dist/shadcn/calendar.d.ts +23 -0
- package/dist/shadcn/calendar.d.ts.map +1 -0
- package/dist/shadcn/calendar.js +163 -0
- package/dist/shadcn/card.d.ts +31 -0
- package/dist/shadcn/card.d.ts.map +1 -0
- package/dist/shadcn/card.js +55 -0
- package/dist/shadcn/carousel.d.ts +51 -0
- package/dist/shadcn/carousel.d.ts.map +1 -0
- package/dist/shadcn/carousel.js +161 -0
- package/dist/shadcn/chart.d.ts +103 -0
- package/dist/shadcn/chart.d.ts.map +1 -0
- package/dist/shadcn/chart.js +248 -0
- package/dist/shadcn/checkbox.d.ts +8 -0
- package/dist/shadcn/checkbox.d.ts.map +1 -0
- package/dist/shadcn/checkbox.js +22 -0
- package/dist/shadcn/collapsible.d.ts +16 -0
- package/dist/shadcn/collapsible.d.ts.map +1 -0
- package/dist/shadcn/collapsible.js +19 -0
- package/dist/shadcn/command.d.ts +61 -0
- package/dist/shadcn/command.d.ts.map +1 -0
- package/dist/shadcn/command.js +123 -0
- package/dist/shadcn/context-menu.d.ts +107 -0
- package/dist/shadcn/context-menu.d.ts.map +1 -0
- package/dist/shadcn/context-menu.js +151 -0
- package/dist/shadcn/dialog.d.ts +57 -0
- package/dist/shadcn/dialog.d.ts.map +1 -0
- package/dist/shadcn/dialog.js +96 -0
- package/dist/shadcn/drawer.d.ts +54 -0
- package/dist/shadcn/drawer.d.ts.map +1 -0
- package/dist/shadcn/drawer.js +96 -0
- package/dist/shadcn/dropdown-menu.d.ts +110 -0
- package/dist/shadcn/dropdown-menu.d.ts.map +1 -0
- package/dist/shadcn/dropdown-menu.js +152 -0
- package/dist/shadcn/form.d.ts +59 -0
- package/dist/shadcn/form.d.ts.map +1 -0
- package/dist/shadcn/form.js +99 -0
- package/dist/shadcn/hover-card.d.ts +20 -0
- package/dist/shadcn/hover-card.d.ts.map +1 -0
- package/dist/shadcn/hover-card.js +26 -0
- package/dist/shadcn/input-otp.d.ts +25 -0
- package/dist/shadcn/input-otp.d.ts.map +1 -0
- package/dist/shadcn/input-otp.js +54 -0
- package/dist/shadcn/input.d.ts +14 -0
- package/dist/shadcn/input.d.ts.map +1 -0
- package/dist/shadcn/input.js +48 -0
- package/dist/shadcn/label.d.ts +8 -0
- package/dist/shadcn/label.d.ts.map +1 -0
- package/dist/shadcn/label.js +16 -0
- package/dist/shadcn/menubar.d.ts +108 -0
- package/dist/shadcn/menubar.d.ts.map +1 -0
- package/dist/shadcn/menubar.js +174 -0
- package/dist/shadcn/navigation-menu.d.ts +79 -0
- package/dist/shadcn/navigation-menu.d.ts.map +1 -0
- package/dist/shadcn/navigation-menu.js +108 -0
- package/dist/shadcn/pagination.d.ts +45 -0
- package/dist/shadcn/pagination.d.ts.map +1 -0
- package/dist/shadcn/pagination.js +83 -0
- package/dist/shadcn/popover.d.ts +19 -0
- package/dist/shadcn/popover.d.ts.map +1 -0
- package/dist/shadcn/popover.js +29 -0
- package/dist/shadcn/progress.d.ts +9 -0
- package/dist/shadcn/progress.d.ts.map +1 -0
- package/dist/shadcn/progress.js +17 -0
- package/dist/shadcn/radio-group.d.ts +12 -0
- package/dist/shadcn/radio-group.d.ts.map +1 -0
- package/dist/shadcn/radio-group.js +32 -0
- package/dist/shadcn/resizable.d.ts +20 -0
- package/dist/shadcn/resizable.d.ts.map +1 -0
- package/dist/shadcn/resizable.js +32 -0
- package/dist/shadcn/scroll-area.d.ts +16 -0
- package/dist/shadcn/scroll-area.d.ts.map +1 -0
- package/dist/shadcn/scroll-area.js +40 -0
- package/dist/shadcn/select.d.ts +63 -0
- package/dist/shadcn/select.d.ts.map +1 -0
- package/dist/shadcn/select.js +120 -0
- package/dist/shadcn/separator.d.ts +10 -0
- package/dist/shadcn/separator.d.ts.map +1 -0
- package/dist/shadcn/separator.js +18 -0
- package/dist/shadcn/sheet.d.ts +48 -0
- package/dist/shadcn/sheet.d.ts.map +1 -0
- package/dist/shadcn/sheet.js +99 -0
- package/dist/shadcn/sidebar.d.ts +200 -0
- package/dist/shadcn/sidebar.d.ts.map +1 -0
- package/dist/shadcn/sidebar.js +528 -0
- package/dist/shadcn/skeleton.d.ts +6 -0
- package/dist/shadcn/skeleton.d.ts.map +1 -0
- package/dist/shadcn/skeleton.js +11 -0
- package/dist/shadcn/slider.d.ts +12 -0
- package/dist/shadcn/slider.d.ts.map +1 -0
- package/dist/shadcn/slider.js +50 -0
- package/dist/shadcn/sonner.d.ts +7 -0
- package/dist/shadcn/sonner.d.ts.map +1 -0
- package/dist/shadcn/sonner.js +20 -0
- package/dist/shadcn/switch.d.ts +8 -0
- package/dist/shadcn/switch.d.ts.map +1 -0
- package/dist/shadcn/switch.js +22 -0
- package/dist/shadcn/table.d.ts +35 -0
- package/dist/shadcn/table.d.ts.map +1 -0
- package/dist/shadcn/table.js +73 -0
- package/dist/shadcn/tabs.d.ts +20 -0
- package/dist/shadcn/tabs.d.ts.map +1 -0
- package/dist/shadcn/tabs.js +40 -0
- package/dist/shadcn/textarea.d.ts +7 -0
- package/dist/shadcn/textarea.d.ts.map +1 -0
- package/dist/shadcn/textarea.js +14 -0
- package/dist/shadcn/toggle-group.d.ts +22 -0
- package/dist/shadcn/toggle-group.d.ts.map +1 -0
- package/dist/shadcn/toggle-group.js +43 -0
- package/dist/shadcn/toggle.d.ts +29 -0
- package/dist/shadcn/toggle.d.ts.map +1 -0
- package/dist/shadcn/toggle.js +31 -0
- package/dist/shadcn/tooltip.d.ts +20 -0
- package/dist/shadcn/tooltip.d.ts.map +1 -0
- package/dist/shadcn/tooltip.js +40 -0
- package/dist/stories/BackgroundSlideshow.stories.d.ts +9 -0
- package/dist/stories/BackgroundSlideshow.stories.d.ts.map +1 -0
- package/dist/stories/BackgroundSlideshow.stories.js +60 -0
- package/dist/stories/BlurryGradient.stories.d.ts +11 -0
- package/dist/stories/BlurryGradient.stories.d.ts.map +1 -0
- package/dist/stories/BlurryGradient.stories.js +53 -0
- package/dist/stories/Box.stories.d.ts +13 -0
- package/dist/stories/Box.stories.d.ts.map +1 -0
- package/dist/stories/Box.stories.js +50 -0
- package/dist/stories/Carousel.stories.d.ts +9 -0
- package/dist/stories/Carousel.stories.d.ts.map +1 -0
- package/dist/stories/Carousel.stories.js +30 -0
- package/dist/stories/Countdown.stories.d.ts +7 -0
- package/dist/stories/Countdown.stories.d.ts.map +1 -0
- package/dist/stories/Countdown.stories.js +11 -0
- package/dist/stories/DefinitionList.stories.d.ts +9 -0
- package/dist/stories/DefinitionList.stories.d.ts.map +1 -0
- package/dist/stories/DefinitionList.stories.js +20 -0
- package/dist/stories/GenericError.stories.d.ts +9 -0
- package/dist/stories/GenericError.stories.d.ts.map +1 -0
- package/dist/stories/GenericError.stories.js +39 -0
- package/dist/stories/Heading.stories.d.ts +15 -0
- package/dist/stories/Heading.stories.d.ts.map +1 -0
- package/dist/stories/Heading.stories.js +61 -0
- package/dist/stories/Highlight.stories.d.ts +8 -0
- package/dist/stories/Highlight.stories.d.ts.map +1 -0
- package/dist/stories/Highlight.stories.js +19 -0
- package/dist/stories/IconButton.stories.d.ts +10 -0
- package/dist/stories/IconButton.stories.d.ts.map +1 -0
- package/dist/stories/IconButton.stories.js +32 -0
- package/dist/stories/If.stories.d.ts +13 -0
- package/dist/stories/If.stories.d.ts.map +1 -0
- package/dist/stories/If.stories.js +54 -0
- package/dist/stories/Iframe.stories.d.ts +8 -0
- package/dist/stories/Iframe.stories.d.ts.map +1 -0
- package/dist/stories/Iframe.stories.js +23 -0
- package/dist/stories/Item.stories.d.ts +10 -0
- package/dist/stories/Item.stories.d.ts.map +1 -0
- package/dist/stories/Item.stories.js +32 -0
- package/dist/stories/Link.stories.d.ts +10 -0
- package/dist/stories/Link.stories.d.ts.map +1 -0
- package/dist/stories/Link.stories.js +36 -0
- package/dist/stories/ListItem.stories.d.ts +9 -0
- package/dist/stories/ListItem.stories.d.ts.map +1 -0
- package/dist/stories/ListItem.stories.js +25 -0
- package/dist/stories/MarkdownContainer.stories.d.ts +11 -0
- package/dist/stories/MarkdownContainer.stories.d.ts.map +1 -0
- package/dist/stories/MarkdownContainer.stories.js +66 -0
- package/dist/stories/PasswordInput.stories.d.ts +9 -0
- package/dist/stories/PasswordInput.stories.d.ts.map +1 -0
- package/dist/stories/PasswordInput.stories.js +27 -0
- package/dist/stories/Picture.stories.d.ts +10 -0
- package/dist/stories/Picture.stories.d.ts.map +1 -0
- package/dist/stories/Picture.stories.js +46 -0
- package/dist/stories/ProtectedEmail.stories.d.ts +10 -0
- package/dist/stories/ProtectedEmail.stories.d.ts.map +1 -0
- package/dist/stories/ProtectedEmail.stories.js +34 -0
- package/dist/stories/Text.stories.d.ts +10 -0
- package/dist/stories/Text.stories.d.ts.map +1 -0
- package/dist/stories/Text.stories.js +31 -0
- package/dist/stories/UnorderedList.stories.d.ts +10 -0
- package/dist/stories/UnorderedList.stories.d.ts.map +1 -0
- package/dist/stories/UnorderedList.stories.js +24 -0
- package/dist/test-setup.d.ts +2 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +1 -0
- package/dist/utils/author.d.ts +9 -0
- package/dist/utils/author.d.ts.map +1 -0
- package/dist/utils/author.js +37 -0
- package/dist/utils/author.test.d.ts +2 -0
- package/dist/utils/author.test.d.ts.map +1 -0
- package/dist/utils/author.test.js +46 -0
- package/dist/utils/cn.d.ts +5 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +10 -0
- package/dist/utils/cn.test.d.ts +2 -0
- package/dist/utils/cn.test.d.ts.map +1 -0
- package/dist/utils/cn.test.js +33 -0
- package/dist/utils/is-route-active.d.ts +3 -0
- package/dist/utils/is-route-active.d.ts.map +1 -0
- package/dist/utils/is-route-active.js +54 -0
- package/dist/utils/is-route-active.test.d.ts +2 -0
- package/dist/utils/is-route-active.test.d.ts.map +1 -0
- package/dist/utils/is-route-active.test.js +61 -0
- package/dist/utils/locale.d.ts +22 -0
- package/dist/utils/locale.d.ts.map +1 -0
- package/dist/utils/locale.js +25 -0
- package/dist/utils/locale.test.d.ts +2 -0
- package/dist/utils/locale.test.d.ts.map +1 -0
- package/dist/utils/locale.test.js +99 -0
- package/dist/utils/text.d.ts +7 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +102 -0
- package/dist/utils/text.test.d.ts +2 -0
- package/dist/utils/text.test.d.ts.map +1 -0
- package/dist/utils/text.test.js +122 -0
- package/package.json +117 -0
- package/src/components/background-slideshow.tsx +172 -0
- package/src/components/blurry-gradient.tsx +97 -0
- package/src/components/box.tsx +45 -0
- package/src/components/carousel.tsx +197 -0
- package/src/components/countdown.tsx +82 -0
- package/src/components/definition-list.tsx +90 -0
- package/src/components/generic-error.tsx +104 -0
- package/src/components/heading.tsx +60 -0
- package/src/components/highlight.tsx +53 -0
- package/src/components/icon-button.tsx +20 -0
- package/src/components/if.tsx +29 -0
- package/src/components/iframe.tsx +19 -0
- package/src/components/item.tsx +340 -0
- package/src/components/leaflet-map.tsx +294 -0
- package/src/components/link.test.tsx +387 -0
- package/src/components/link.tsx +206 -0
- package/src/components/list-item.tsx +30 -0
- package/src/components/maptiler-map.tsx +181 -0
- package/src/components/markdown-container.tsx +153 -0
- package/src/components/password-input.tsx +49 -0
- package/src/components/picture.tsx +107 -0
- package/src/components/protected-email.tsx +49 -0
- package/src/components/text.tsx +38 -0
- package/src/components/unordered-list.tsx +32 -0
- package/src/hooks/use-current-route-data.ts +18 -0
- package/src/hooks/use-focus-search.ts +20 -0
- package/src/hooks/use-matches-data.ts +19 -0
- package/src/hooks/use-media-query.ts +33 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/hooks/use-nonce.test.ts +35 -0
- package/src/hooks/use-nonce.ts +20 -0
- package/src/hooks/use-orientation.ts +48 -0
- package/src/hooks/use-user.tsx +72 -0
- package/src/stories/BackgroundSlideshow.stories.tsx +68 -0
- package/src/stories/BlurryGradient.stories.tsx +62 -0
- package/src/stories/Box.stories.tsx +83 -0
- package/src/stories/Carousel.stories.tsx +95 -0
- package/src/stories/Countdown.stories.tsx +16 -0
- package/src/stories/DefinitionList.stories.tsx +51 -0
- package/src/stories/GenericError.stories.tsx +58 -0
- package/src/stories/Heading.stories.tsx +82 -0
- package/src/stories/Highlight.stories.tsx +28 -0
- package/src/stories/IconButton.stories.tsx +90 -0
- package/src/stories/If.stories.tsx +72 -0
- package/src/stories/Iframe.stories.tsx +29 -0
- package/src/stories/Item.stories.tsx +79 -0
- package/src/stories/Link.stories.tsx +58 -0
- package/src/stories/ListItem.stories.tsx +37 -0
- package/src/stories/MarkdownContainer.stories.tsx +76 -0
- package/src/stories/PasswordInput.stories.tsx +34 -0
- package/src/stories/Picture.stories.tsx +54 -0
- package/src/stories/ProtectedEmail.stories.tsx +57 -0
- package/src/stories/Text.stories.tsx +44 -0
- package/src/stories/UnorderedList.stories.tsx +73 -0
- package/src/styles/storybook.css +1 -0
- package/src/styles/tailwind.css +7 -0
- package/src/test-setup.ts +1 -0
- package/src/utils/author.test.ts +54 -0
- package/src/utils/author.tsx +73 -0
- package/src/utils/cn.test.ts +48 -0
- package/src/utils/cn.ts +14 -0
- package/src/utils/is-route-active.test.ts +80 -0
- package/src/utils/is-route-active.ts +100 -0
- package/src/utils/locale.test.ts +148 -0
- package/src/utils/locale.ts +127 -0
- package/src/utils/text.test.ts +152 -0
- package/src/utils/text.tsx +209 -0
- package/src/vite-env.d.ts +1 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { MemoryRouter } from 'react-router';
|
|
3
|
+
import { Link } from '../components/link';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Link> = {
|
|
6
|
+
component: Link,
|
|
7
|
+
decorators: [
|
|
8
|
+
(Story) => (
|
|
9
|
+
<MemoryRouter>
|
|
10
|
+
<Story />
|
|
11
|
+
</MemoryRouter>
|
|
12
|
+
),
|
|
13
|
+
],
|
|
14
|
+
parameters: {
|
|
15
|
+
layout: 'padded',
|
|
16
|
+
},
|
|
17
|
+
tags: ['autodocs'],
|
|
18
|
+
title: 'Components/Link',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof Link>;
|
|
23
|
+
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
children: 'Default Link',
|
|
27
|
+
to: '/example',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const External: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
children: 'External Link',
|
|
34
|
+
to: 'https://example.com',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const WithGermanText: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
children: 'Größenübersicht',
|
|
41
|
+
to: '/sizes',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const AllVariants: Story = {
|
|
46
|
+
render: () => (
|
|
47
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
48
|
+
<Link to="/internal">Internal Link</Link>
|
|
49
|
+
<Link to="https://example.com">External Link</Link>
|
|
50
|
+
<Link
|
|
51
|
+
className="text-blue-600 underline"
|
|
52
|
+
to="/styled"
|
|
53
|
+
>
|
|
54
|
+
Styled Link
|
|
55
|
+
</Link>
|
|
56
|
+
</div>
|
|
57
|
+
),
|
|
58
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ListItem } from '../components/list-item';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof ListItem> = {
|
|
5
|
+
component: ListItem,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'padded',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/ListItem',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof ListItem>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
children: 'List item content',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const InList: Story = {
|
|
23
|
+
render: () => (
|
|
24
|
+
<ul>
|
|
25
|
+
<ListItem>First item</ListItem>
|
|
26
|
+
<ListItem>Second item</ListItem>
|
|
27
|
+
<ListItem>Third item</ListItem>
|
|
28
|
+
</ul>
|
|
29
|
+
),
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const WithCustomClass: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
children: 'Styled list item',
|
|
35
|
+
className: 'font-bold text-blue-600',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { MarkdownContainer } from '../components/markdown-container';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof MarkdownContainer> = {
|
|
5
|
+
component: MarkdownContainer,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'padded',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/MarkdownContainer',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof MarkdownContainer>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
children: `# Hello World
|
|
19
|
+
|
|
20
|
+
This is a **markdown** paragraph with *italic* text.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- List item 1
|
|
25
|
+
- List item 2
|
|
26
|
+
- List item 3
|
|
27
|
+
|
|
28
|
+
[Link to example](https://example.com)`,
|
|
29
|
+
locale: 'en',
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const GermanLocale: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
children: `# Willkommen
|
|
36
|
+
|
|
37
|
+
Dies ist ein "Beispieltext" mit typografischen Anführungszeichen.
|
|
38
|
+
|
|
39
|
+
## Funktionen
|
|
40
|
+
|
|
41
|
+
- Punkt 1
|
|
42
|
+
- Punkt 2`,
|
|
43
|
+
locale: 'de',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const WithTruncation: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
children:
|
|
50
|
+
'This is a long paragraph that will be truncated. It contains multiple sentences. Each sentence adds more content. The truncation should work properly.',
|
|
51
|
+
locale: 'en',
|
|
52
|
+
sentences: 2,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const WithParagraphLimit: Story = {
|
|
57
|
+
args: {
|
|
58
|
+
children: `First paragraph with some content.
|
|
59
|
+
|
|
60
|
+
Second paragraph with more content.
|
|
61
|
+
|
|
62
|
+
Third paragraph that should be hidden.
|
|
63
|
+
|
|
64
|
+
Fourth paragraph also hidden.`,
|
|
65
|
+
locale: 'en',
|
|
66
|
+
paragraphs: 2,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const WithCharacterLimit: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
characters: 50,
|
|
73
|
+
children: 'This is a long text that will be truncated after a certain number of characters.',
|
|
74
|
+
locale: 'en',
|
|
75
|
+
},
|
|
76
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { PasswordInput } from '../components/password-input';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof PasswordInput> = {
|
|
5
|
+
component: PasswordInput,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'padded',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/PasswordInput',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof PasswordInput>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
placeholder: 'Enter password',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const WithValue: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
defaultValue: 'secretpassword',
|
|
25
|
+
placeholder: 'Enter password',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const WithCustomClass: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
className: 'border border-gray-300 rounded px-3 py-2',
|
|
32
|
+
placeholder: 'Styled password input',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Picture } from '../components/picture';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Picture> = {
|
|
5
|
+
component: Picture,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'padded',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/Picture',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof Picture>;
|
|
15
|
+
|
|
16
|
+
export const SimpleImage: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
alt: 'Placeholder image',
|
|
19
|
+
baseUrl: 'https://via.placeholder.com/400x300',
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const WithFormats: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
alt: 'Responsive image',
|
|
26
|
+
baseUrl: 'https://via.placeholder.com/{format}',
|
|
27
|
+
formats: [
|
|
28
|
+
{ size: '480x360', width: 480 },
|
|
29
|
+
{ size: '800x600', width: 800 },
|
|
30
|
+
{ size: '1200x900', width: 1200 },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const WithCustomSizes: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
alt: 'Custom sizes image',
|
|
38
|
+
baseUrl: 'https://via.placeholder.com/{format}',
|
|
39
|
+
formats: [
|
|
40
|
+
{ size: '320x240', width: 320 },
|
|
41
|
+
{ size: '640x480', width: 640 },
|
|
42
|
+
],
|
|
43
|
+
sizes: '(max-width: 640px) 320px, 640px',
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const WithClassName: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
alt: 'Styled image',
|
|
50
|
+
baseUrl: 'https://via.placeholder.com/400x300',
|
|
51
|
+
className: 'rounded-lg shadow-lg',
|
|
52
|
+
imgClassName: 'object-cover',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ProtectedEmail } from '../components/protected-email';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof ProtectedEmail> = {
|
|
5
|
+
component: ProtectedEmail,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'padded',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/ProtectedEmail',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof ProtectedEmail>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
domain: 'example.com',
|
|
19
|
+
username: 'contact',
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const WithCustomText: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
domain: 'example.com',
|
|
26
|
+
text: 'Send us an email',
|
|
27
|
+
username: 'info',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const WithClassName: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
className: 'text-blue-600 underline hover:text-blue-800',
|
|
34
|
+
domain: 'company.org',
|
|
35
|
+
username: 'support',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const MultipleEmails: Story = {
|
|
40
|
+
render: () => (
|
|
41
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
42
|
+
<ProtectedEmail
|
|
43
|
+
domain="example.com"
|
|
44
|
+
username="sales"
|
|
45
|
+
/>
|
|
46
|
+
<ProtectedEmail
|
|
47
|
+
domain="example.com"
|
|
48
|
+
username="support"
|
|
49
|
+
/>
|
|
50
|
+
<ProtectedEmail
|
|
51
|
+
domain="example.com"
|
|
52
|
+
text="General Inquiries"
|
|
53
|
+
username="info"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
),
|
|
57
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Text } from '../components/text';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Text> = {
|
|
5
|
+
component: Text,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'padded',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/Text',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof Text>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
children: 'This is default text content.',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const Subtitle: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
children: 'This is subtitle text with larger size.',
|
|
25
|
+
variant: 'subtitle',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const Code: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
children: "const example = 'monospace code text';",
|
|
32
|
+
variant: 'code',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const AllVariants: Story = {
|
|
37
|
+
render: () => (
|
|
38
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
|
|
39
|
+
<Text variant="primary">Primary text (default)</Text>
|
|
40
|
+
<Text variant="subtitle">Subtitle text</Text>
|
|
41
|
+
<Text variant="code">Code text with monospace font</Text>
|
|
42
|
+
</div>
|
|
43
|
+
),
|
|
44
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ListItem } from '../components/list-item';
|
|
3
|
+
import { UnorderedList } from '../components/unordered-list';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof UnorderedList> = {
|
|
6
|
+
component: UnorderedList,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'padded',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
title: 'Components/UnorderedList',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof UnorderedList>;
|
|
16
|
+
|
|
17
|
+
export const Default: Story = {
|
|
18
|
+
render: () => (
|
|
19
|
+
<UnorderedList>
|
|
20
|
+
<ListItem>Item 1</ListItem>
|
|
21
|
+
<ListItem>Item 2</ListItem>
|
|
22
|
+
<ListItem>Item 3</ListItem>
|
|
23
|
+
</UnorderedList>
|
|
24
|
+
),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const Inline: Story = {
|
|
28
|
+
render: () => (
|
|
29
|
+
<UnorderedList variant="inline">
|
|
30
|
+
<ListItem>Tag 1</ListItem>
|
|
31
|
+
<ListItem>Tag 2</ListItem>
|
|
32
|
+
<ListItem>Tag 3</ListItem>
|
|
33
|
+
</UnorderedList>
|
|
34
|
+
),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const Unstyled: Story = {
|
|
38
|
+
render: () => (
|
|
39
|
+
<UnorderedList variant="unstyled">
|
|
40
|
+
<ListItem>No bullet 1</ListItem>
|
|
41
|
+
<ListItem>No bullet 2</ListItem>
|
|
42
|
+
<ListItem>No bullet 3</ListItem>
|
|
43
|
+
</UnorderedList>
|
|
44
|
+
),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const AllVariants: Story = {
|
|
48
|
+
render: () => (
|
|
49
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
|
|
50
|
+
<div>
|
|
51
|
+
<h4>Primary (default)</h4>
|
|
52
|
+
<UnorderedList variant="primary">
|
|
53
|
+
<ListItem>Item 1</ListItem>
|
|
54
|
+
<ListItem>Item 2</ListItem>
|
|
55
|
+
</UnorderedList>
|
|
56
|
+
</div>
|
|
57
|
+
<div>
|
|
58
|
+
<h4>Inline</h4>
|
|
59
|
+
<UnorderedList variant="inline">
|
|
60
|
+
<ListItem>Item 1</ListItem>
|
|
61
|
+
<ListItem>Item 2</ListItem>
|
|
62
|
+
</UnorderedList>
|
|
63
|
+
</div>
|
|
64
|
+
<div>
|
|
65
|
+
<h4>Unstyled</h4>
|
|
66
|
+
<UnorderedList variant="unstyled">
|
|
67
|
+
<ListItem>Item 1</ListItem>
|
|
68
|
+
<ListItem>Item 2</ListItem>
|
|
69
|
+
</UnorderedList>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
),
|
|
73
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { parseAuthorString } from './author';
|
|
3
|
+
|
|
4
|
+
describe('parseAuthorString', () => {
|
|
5
|
+
test('parses name only', () => {
|
|
6
|
+
expect(parseAuthorString('John Doe')).toEqual({ name: 'John Doe' });
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
test('parses name and email', () => {
|
|
10
|
+
expect(parseAuthorString('John Doe <john@example.com>')).toEqual({
|
|
11
|
+
email: 'john@example.com',
|
|
12
|
+
name: 'John Doe',
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('parses name and URL', () => {
|
|
17
|
+
expect(parseAuthorString('John Doe (https://example.com)')).toEqual({
|
|
18
|
+
name: 'John Doe',
|
|
19
|
+
url: 'https://example.com',
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('parses name, email, and URL', () => {
|
|
24
|
+
expect(parseAuthorString('John Doe <john@example.com> (https://example.com)')).toEqual({
|
|
25
|
+
email: 'john@example.com',
|
|
26
|
+
name: 'John Doe',
|
|
27
|
+
url: 'https://example.com',
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('handles email only (no name)', () => {
|
|
32
|
+
expect(parseAuthorString('<john@example.com>')).toEqual({
|
|
33
|
+
email: 'john@example.com',
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('handles whitespace in name', () => {
|
|
38
|
+
expect(parseAuthorString(' John Doe <john@example.com>')).toEqual({
|
|
39
|
+
email: 'john@example.com',
|
|
40
|
+
name: 'John Doe',
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('returns empty object for empty string', () => {
|
|
45
|
+
expect(parseAuthorString('')).toEqual({});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('handles relative URL', () => {
|
|
49
|
+
expect(parseAuthorString('John Doe (/about/john)')).toEqual({
|
|
50
|
+
name: 'John Doe',
|
|
51
|
+
url: '/about/john',
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
type AuthorInfo = {
|
|
2
|
+
name?: string;
|
|
3
|
+
email?: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const regex = /^(.*?)\s*(?:<([^>]+)>)?\s*(?:\(([^)]+)\))?$/;
|
|
8
|
+
|
|
9
|
+
export function parseAuthorString(input: string): AuthorInfo {
|
|
10
|
+
const match = input.match(regex);
|
|
11
|
+
|
|
12
|
+
if (match) {
|
|
13
|
+
const [, name, email, url] = match;
|
|
14
|
+
|
|
15
|
+
const result: AuthorInfo = {};
|
|
16
|
+
|
|
17
|
+
if (email) {
|
|
18
|
+
result.email = email;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const trimmedName = name?.trim();
|
|
22
|
+
|
|
23
|
+
if (trimmedName) {
|
|
24
|
+
result.name = trimmedName;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (url) {
|
|
28
|
+
result.url = url;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function generateLinkFromAuthorString(input: string): React.ReactNode {
|
|
38
|
+
const match = input.match(regex);
|
|
39
|
+
if (match) {
|
|
40
|
+
const [, name, email, url] = match.map((part) => {
|
|
41
|
+
return part?.trim();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Generate email link if email is present
|
|
45
|
+
if (email) {
|
|
46
|
+
return (
|
|
47
|
+
<a
|
|
48
|
+
className={'u-email p-name'}
|
|
49
|
+
href={`mailto:${email}`}
|
|
50
|
+
>
|
|
51
|
+
{name}
|
|
52
|
+
</a>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Generate URL link if URL is present (including relative URLs that start with a slash)
|
|
57
|
+
if (url && (url.startsWith('/') || url.startsWith('http'))) {
|
|
58
|
+
return (
|
|
59
|
+
<a
|
|
60
|
+
className={'u-url p-name'}
|
|
61
|
+
href={url}
|
|
62
|
+
>
|
|
63
|
+
{name}
|
|
64
|
+
</a>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Return plain name with microformat class if only name is present
|
|
69
|
+
return <span className={'p-name'}>{name}</span>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { cn } from './cn';
|
|
4
|
+
|
|
5
|
+
test('removes conflicting classes using twMerge', () => {
|
|
6
|
+
const classes = cn('text-red-500', 'text-blue-500');
|
|
7
|
+
|
|
8
|
+
expect(classes).toBe('text-blue-500');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test('merges multiple classes into a single string', () => {
|
|
12
|
+
const classes = cn('text-red-500', 'font-bold');
|
|
13
|
+
|
|
14
|
+
expect(classes).toBe('text-red-500 font-bold');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('removes empty classes', () => {
|
|
18
|
+
const classes = cn('text-red-500', '', 'font-bold');
|
|
19
|
+
|
|
20
|
+
expect(classes).toBe('text-red-500 font-bold');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('removes undefined classes', () => {
|
|
24
|
+
const classes = cn('text-red-500', undefined, 'font-bold');
|
|
25
|
+
|
|
26
|
+
expect(classes).toBe('text-red-500 font-bold');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('removes null classes', () => {
|
|
30
|
+
const classes = cn('text-red-500', null, 'font-bold');
|
|
31
|
+
|
|
32
|
+
expect(classes).toBe('text-red-500 font-bold');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('resolves nested arrays', () => {
|
|
36
|
+
const classes = cn('text-red-500', ['bg-blue-500', 'font-bold']);
|
|
37
|
+
|
|
38
|
+
expect(classes).toBe('text-red-500 bg-blue-500 font-bold');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('resolves nested objects', () => {
|
|
42
|
+
const classes = cn('text-red-500', {
|
|
43
|
+
'bg-blue-500': true,
|
|
44
|
+
'font-bold': true,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(classes).toBe('text-red-500 bg-blue-500 font-bold');
|
|
48
|
+
});
|
package/src/utils/cn.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { cx, defineConfig } from 'cva';
|
|
2
|
+
import { twMerge } from 'fluid-tailwindcss/tailwind-merge';
|
|
3
|
+
|
|
4
|
+
export type { VariantProps } from 'cva';
|
|
5
|
+
|
|
6
|
+
export const { cva, compose } = defineConfig({
|
|
7
|
+
hooks: {
|
|
8
|
+
onComplete: (className: string) => {
|
|
9
|
+
return twMerge(className);
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const cn = (...inputs: Parameters<typeof cx>) => twMerge(cx(inputs));
|