@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,107 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { cn } from '../utils/cn';
|
|
3
|
+
|
|
4
|
+
// Define screen size variants for responsive images
|
|
5
|
+
// Define screen size variants for responsive images (used in srcset generation)
|
|
6
|
+
export const screenSizeVariants = {
|
|
7
|
+
lg: 1280,
|
|
8
|
+
max: 1920,
|
|
9
|
+
md: 960,
|
|
10
|
+
min: 360,
|
|
11
|
+
sm: 640,
|
|
12
|
+
xl: 1600,
|
|
13
|
+
xs: 480,
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
// Define image format for different providers
|
|
17
|
+
export type ImageFormat = {
|
|
18
|
+
size: string; // Size descriptor (e.g., '480x360', 'sm', etc.)
|
|
19
|
+
width: number; // Width in pixels for srcset
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface PictureProps {
|
|
23
|
+
alt: string;
|
|
24
|
+
baseUrl: string; // Base URL template that can include placeholders
|
|
25
|
+
className?: string;
|
|
26
|
+
formats?: ImageFormat[]; // Custom formats if needed
|
|
27
|
+
imgClassName?: string; // Additional class for the img element
|
|
28
|
+
placeholder?: string; // Placeholder to replace in baseUrl
|
|
29
|
+
sizes?: string; // Custom sizes attribute
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Generic Picture component that works with any image provider
|
|
34
|
+
*
|
|
35
|
+
* @param alt - Alt text for the image
|
|
36
|
+
* @param baseUrl - Base URL with optional placeholder (e.g., 'https://example.com/images/{format}/image.jpg')
|
|
37
|
+
* @param className - Optional class for the picture element
|
|
38
|
+
* @param formats - Custom formats with size and width
|
|
39
|
+
* @param imgClassName - Optional class for the img element
|
|
40
|
+
* @param placeholder - Placeholder to replace in baseUrl (default: '{format}')
|
|
41
|
+
* @param sizes - Custom sizes attribute
|
|
42
|
+
*/
|
|
43
|
+
const Picture: React.FC<PictureProps> = ({
|
|
44
|
+
alt,
|
|
45
|
+
baseUrl,
|
|
46
|
+
className,
|
|
47
|
+
formats,
|
|
48
|
+
imgClassName,
|
|
49
|
+
placeholder = '{format}',
|
|
50
|
+
sizes = '(max-width: 480px) 480px, (max-width: 768px) 600px, (max-width: 1200px) 1024px, 1920px',
|
|
51
|
+
}) => {
|
|
52
|
+
// Default formats if none provided
|
|
53
|
+
const imageFormats = formats || [
|
|
54
|
+
{ size: '480x360', width: 480 },
|
|
55
|
+
{ size: '600x600', width: 600 },
|
|
56
|
+
{ size: '1024x768', width: 1024 },
|
|
57
|
+
{ size: '1920x1440', width: 1920 },
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
if (imageFormats.length === 0) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Check if this is a simple image without size variations
|
|
65
|
+
// (single format with empty size string, or no placeholder in URL)
|
|
66
|
+
const isSimpleImage =
|
|
67
|
+
(imageFormats.length === 1 && imageFormats[0]?.size === '') || !baseUrl.includes(placeholder);
|
|
68
|
+
|
|
69
|
+
if (isSimpleImage) {
|
|
70
|
+
return (
|
|
71
|
+
<img
|
|
72
|
+
alt={alt}
|
|
73
|
+
className={cn(className, imgClassName)}
|
|
74
|
+
src={baseUrl}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Generate srcset by replacing placeholder in baseUrl
|
|
80
|
+
const srcSet = imageFormats
|
|
81
|
+
.map(({ size, width }) => {
|
|
82
|
+
const url = baseUrl.replace(placeholder, size);
|
|
83
|
+
return `${url} ${width}w`;
|
|
84
|
+
})
|
|
85
|
+
.join(', ');
|
|
86
|
+
|
|
87
|
+
// Use the first format as the default src
|
|
88
|
+
const defaultFormat = imageFormats[0];
|
|
89
|
+
// Add a null check for defaultFormat
|
|
90
|
+
const defaultSrc = defaultFormat ? baseUrl.replace(placeholder, defaultFormat.size) : baseUrl;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<picture className={className}>
|
|
94
|
+
<source
|
|
95
|
+
sizes={sizes}
|
|
96
|
+
srcSet={srcSet}
|
|
97
|
+
/>
|
|
98
|
+
<img
|
|
99
|
+
alt={alt}
|
|
100
|
+
className={cn(imgClassName)}
|
|
101
|
+
src={defaultSrc}
|
|
102
|
+
/>
|
|
103
|
+
</picture>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export { Picture };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ProtectedEmailProps {
|
|
4
|
+
username: string;
|
|
5
|
+
domain: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ProtectedEmail component that obfuscates email addresses to protect from scrapers.
|
|
12
|
+
* The email is only assembled client-side with JavaScript, making it harder for scrapers to extract.
|
|
13
|
+
*
|
|
14
|
+
* @param username - The part before the @ symbol
|
|
15
|
+
* @param domain - The part after the @ symbol
|
|
16
|
+
* @param text - Optional display text (defaults to username(at)domain)
|
|
17
|
+
* @param className - Optional CSS class name
|
|
18
|
+
*/
|
|
19
|
+
export function ProtectedEmail({ username, domain, text, className }: ProtectedEmailProps) {
|
|
20
|
+
const [mounted, setMounted] = useState(false);
|
|
21
|
+
|
|
22
|
+
// Only assemble the email on the client side
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setMounted(true);
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
// Display format before JavaScript runs (or for users without JS)
|
|
28
|
+
const fallbackText = text || `${username}(at)${domain}`;
|
|
29
|
+
|
|
30
|
+
// Only assemble the actual mailto link on the client side
|
|
31
|
+
const handleClick = (e: React.MouseEvent) => {
|
|
32
|
+
if (mounted) {
|
|
33
|
+
window.location.href = `mailto:${username}@${domain}`;
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<a
|
|
40
|
+
aria-label={`Email address: ${username} at ${domain}`}
|
|
41
|
+
className={className}
|
|
42
|
+
data-email-protected="true"
|
|
43
|
+
href={mounted ? '#email-protected' : undefined}
|
|
44
|
+
onClick={handleClick}
|
|
45
|
+
>
|
|
46
|
+
{fallbackText}
|
|
47
|
+
</a>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import { cva, type VariantProps } from '../utils/cn';
|
|
3
|
+
|
|
4
|
+
const text = cva({
|
|
5
|
+
base: ['relative', 'block'],
|
|
6
|
+
defaultVariants: {
|
|
7
|
+
themeColor: 'primary',
|
|
8
|
+
variant: 'primary',
|
|
9
|
+
},
|
|
10
|
+
variants: {
|
|
11
|
+
themeColor: {
|
|
12
|
+
primary: [],
|
|
13
|
+
},
|
|
14
|
+
variant: {
|
|
15
|
+
code: ['font-light', 'font-monospace'],
|
|
16
|
+
primary: [],
|
|
17
|
+
subtitle: ['text-lg'],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export interface TextProps extends ComponentProps<'p'>, VariantProps<typeof text> {}
|
|
23
|
+
|
|
24
|
+
export const Text = (props: TextProps) => {
|
|
25
|
+
const { children, className, variant, themeColor } = props;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
className={text({
|
|
30
|
+
className,
|
|
31
|
+
themeColor,
|
|
32
|
+
variant,
|
|
33
|
+
})}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
import { cva, type VariantProps } from '../utils/cn';
|
|
3
|
+
|
|
4
|
+
const ul = cva({
|
|
5
|
+
defaultVariants: {
|
|
6
|
+
variant: 'primary',
|
|
7
|
+
},
|
|
8
|
+
variants: {
|
|
9
|
+
variant: {
|
|
10
|
+
inline: ['flex', 'flex-wrap', 'list-none'],
|
|
11
|
+
primary: [],
|
|
12
|
+
unstyled: ['list-none', 'p-0'],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export interface UnorderedListProps extends ComponentProps<'ul'>, VariantProps<typeof ul> {}
|
|
18
|
+
|
|
19
|
+
export const UnorderedList = (props: UnorderedListProps) => {
|
|
20
|
+
const { children, className, variant } = props;
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ul
|
|
24
|
+
className={ul({
|
|
25
|
+
className,
|
|
26
|
+
variant,
|
|
27
|
+
})}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</ul>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useLocation, useMatches } from 'react-router';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This base hook is used to access data related to the current route
|
|
6
|
+
* @returns {JSON|undefined} The router data or undefined if not found
|
|
7
|
+
*/
|
|
8
|
+
export function useCurrentRouteData<HeaderData>() {
|
|
9
|
+
const location = useLocation();
|
|
10
|
+
const matchingRoutes = useMatches();
|
|
11
|
+
const route = useMemo(() => {
|
|
12
|
+
return matchingRoutes.find((route) => {
|
|
13
|
+
return route.pathname === location.pathname;
|
|
14
|
+
});
|
|
15
|
+
}, [matchingRoutes, location]);
|
|
16
|
+
|
|
17
|
+
return route?.data || (undefined as HeaderData);
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Focuses on the field when user clicks cmd + k or ctrl + k */
|
|
5
|
+
export function useFocusSearch(ref: RefObject<HTMLInputElement>) {
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
function handleKeyDown(event: KeyboardEvent) {
|
|
8
|
+
if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
|
|
9
|
+
event.preventDefault();
|
|
10
|
+
ref?.current?.focus();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
15
|
+
|
|
16
|
+
return () => {
|
|
17
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
18
|
+
};
|
|
19
|
+
}, [ref]);
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useMatches } from 'react-router';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This base hook is used in other hooks to quickly search for specific data
|
|
6
|
+
* across all loader data using useMatches.
|
|
7
|
+
* @param {string} id The route id
|
|
8
|
+
* @returns {JSON|undefined} The router data or undefined if not found
|
|
9
|
+
*/
|
|
10
|
+
export function useMatchesData<T>(id: string): T | undefined {
|
|
11
|
+
const matchingRoutes = useMatches();
|
|
12
|
+
const route = useMemo(() => {
|
|
13
|
+
return matchingRoutes.find((route) => {
|
|
14
|
+
return route.id === id;
|
|
15
|
+
});
|
|
16
|
+
}, [matchingRoutes, id]);
|
|
17
|
+
|
|
18
|
+
return (route?.data as T) || undefined;
|
|
19
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A hook that returns a boolean indicating whether the current viewport matches the provided media query
|
|
5
|
+
* @param query The media query to check against (e.g. '(min-width: 768px)')
|
|
6
|
+
* @returns A boolean indicating whether the media query matches
|
|
7
|
+
*/
|
|
8
|
+
export function useMediaQuery(query: string): boolean {
|
|
9
|
+
const [matches, setMatches] = useState(false);
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
// Create a media query list
|
|
13
|
+
const mediaQuery = window.matchMedia(query);
|
|
14
|
+
|
|
15
|
+
// Set the initial value
|
|
16
|
+
setMatches(mediaQuery.matches);
|
|
17
|
+
|
|
18
|
+
// Define a callback function to handle changes
|
|
19
|
+
const handleChange = (event: MediaQueryListEvent) => {
|
|
20
|
+
setMatches(event.matches);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Add the event listener
|
|
24
|
+
mediaQuery.addEventListener('change', handleChange);
|
|
25
|
+
|
|
26
|
+
// Clean up
|
|
27
|
+
return () => {
|
|
28
|
+
mediaQuery.removeEventListener('change', handleChange);
|
|
29
|
+
};
|
|
30
|
+
}, [query]);
|
|
31
|
+
|
|
32
|
+
return matches;
|
|
33
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
const MOBILE_BREAKPOINT = 768;
|
|
4
|
+
|
|
5
|
+
export function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = useState<boolean | undefined>(undefined);
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
10
|
+
const onChange = () => {
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
12
|
+
};
|
|
13
|
+
mql.addEventListener('change', onChange);
|
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
15
|
+
return () => mql.removeEventListener('change', onChange);
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return !!isMobile;
|
|
19
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { generateNonce } from './use-nonce';
|
|
3
|
+
|
|
4
|
+
describe('generateNonce', () => {
|
|
5
|
+
test('generates a string', () => {
|
|
6
|
+
const nonce = generateNonce();
|
|
7
|
+
expect(typeof nonce).toBe('string');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('generates a non-empty string', () => {
|
|
11
|
+
const nonce = generateNonce();
|
|
12
|
+
expect(nonce.length).toBeGreaterThan(0);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test('generates base64-encoded string', () => {
|
|
16
|
+
const nonce = generateNonce();
|
|
17
|
+
// Base64 characters: A-Z, a-z, 0-9, +, /, =
|
|
18
|
+
expect(nonce).toMatch(/^[A-Za-z0-9+/=]+$/);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('generates unique nonces', () => {
|
|
22
|
+
const nonces = new Set<string>();
|
|
23
|
+
for (let i = 0; i < 100; i++) {
|
|
24
|
+
nonces.add(generateNonce());
|
|
25
|
+
}
|
|
26
|
+
// All 100 nonces should be unique
|
|
27
|
+
expect(nonces.size).toBe(100);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('generates nonce of expected length', () => {
|
|
31
|
+
const nonce = generateNonce();
|
|
32
|
+
// 16 bytes encoded in base64 = 24 characters (with padding)
|
|
33
|
+
expect(nonce.length).toBe(24);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nonce Provider.
|
|
3
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce
|
|
4
|
+
*/
|
|
5
|
+
import { createContext, useContext } from 'react';
|
|
6
|
+
|
|
7
|
+
export const NonceContext = createContext<string>('');
|
|
8
|
+
export const NonceProvider = NonceContext.Provider;
|
|
9
|
+
|
|
10
|
+
export const useNonce = () => useContext(NonceContext);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generate a cryptographically secure nonce for CSP.
|
|
14
|
+
* @returns A base64-encoded random nonce
|
|
15
|
+
*/
|
|
16
|
+
export function generateNonce(): string {
|
|
17
|
+
const array = new Uint8Array(16);
|
|
18
|
+
crypto.getRandomValues(array);
|
|
19
|
+
return btoa(String.fromCharCode(...array));
|
|
20
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Orientation type representing device orientation
|
|
5
|
+
*/
|
|
6
|
+
export type Orientation = 'portrait' | 'landscape';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Hook that tracks the current device orientation
|
|
10
|
+
* @returns The current orientation ('portrait' or 'landscape')
|
|
11
|
+
*/
|
|
12
|
+
export function useOrientation(): Orientation {
|
|
13
|
+
const [orientation, setOrientation] = useState<Orientation>(() => {
|
|
14
|
+
// Initial orientation check
|
|
15
|
+
if (typeof window !== 'undefined') {
|
|
16
|
+
return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
|
|
17
|
+
}
|
|
18
|
+
return 'portrait'; // Default for SSR
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (typeof window === 'undefined') {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Handler to call on window resize
|
|
27
|
+
const handleResize = () => {
|
|
28
|
+
setOrientation(window.innerHeight > window.innerWidth ? 'portrait' : 'landscape');
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Set resize listener
|
|
32
|
+
window.addEventListener('resize', handleResize);
|
|
33
|
+
|
|
34
|
+
// Optional: Listen to orientation change event for mobile devices
|
|
35
|
+
window.addEventListener('orientationchange', handleResize);
|
|
36
|
+
|
|
37
|
+
// Call handler right away to set initial orientation
|
|
38
|
+
handleResize();
|
|
39
|
+
|
|
40
|
+
// Clean up
|
|
41
|
+
return () => {
|
|
42
|
+
window.removeEventListener('resize', handleResize);
|
|
43
|
+
window.removeEventListener('orientationchange', handleResize);
|
|
44
|
+
};
|
|
45
|
+
}, []);
|
|
46
|
+
|
|
47
|
+
return orientation;
|
|
48
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { User } from '@supabase/supabase-js';
|
|
2
|
+
import { createContext, type ReactNode, useContext } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Context for storing and accessing the current authenticated user
|
|
6
|
+
*/
|
|
7
|
+
export interface UserContextType {
|
|
8
|
+
/**
|
|
9
|
+
* The current authenticated user, or null if not authenticated
|
|
10
|
+
*/
|
|
11
|
+
user: User | null;
|
|
12
|
+
/**
|
|
13
|
+
* Whether the user data is currently loading
|
|
14
|
+
*/
|
|
15
|
+
isLoading: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Default context value when no provider is present
|
|
20
|
+
*/
|
|
21
|
+
const defaultContextValue: UserContextType = {
|
|
22
|
+
isLoading: false,
|
|
23
|
+
user: null,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Context for storing and accessing the current authenticated user
|
|
28
|
+
*/
|
|
29
|
+
export const UserContext = createContext<UserContextType>(defaultContextValue);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Props for the UserContextProvider component
|
|
33
|
+
*/
|
|
34
|
+
export interface UserContextProviderProps {
|
|
35
|
+
/**
|
|
36
|
+
* The current authenticated user, or null if not authenticated
|
|
37
|
+
*/
|
|
38
|
+
user: User | null;
|
|
39
|
+
/**
|
|
40
|
+
* Whether the user data is currently loading
|
|
41
|
+
*/
|
|
42
|
+
isLoading?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Child components that will have access to the user context
|
|
45
|
+
*/
|
|
46
|
+
children: ReactNode;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Provider component for the UserContext
|
|
51
|
+
*/
|
|
52
|
+
export function UserContextProvider({
|
|
53
|
+
user,
|
|
54
|
+
isLoading = false,
|
|
55
|
+
children,
|
|
56
|
+
}: UserContextProviderProps) {
|
|
57
|
+
return <UserContext.Provider value={{ isLoading, user }}>{children}</UserContext.Provider>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Hook to access the current authenticated user from the UserContext
|
|
62
|
+
* @returns The current user context containing the user object and loading state
|
|
63
|
+
*/
|
|
64
|
+
export function useUser(): UserContextType {
|
|
65
|
+
const context = useContext(UserContext);
|
|
66
|
+
|
|
67
|
+
if (context === undefined) {
|
|
68
|
+
throw new Error('useUser must be used within a UserContextProvider');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return context;
|
|
72
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { BackgroundSlideshow, type ImageData } from '../components/background-slideshow';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof BackgroundSlideshow> = {
|
|
5
|
+
component: BackgroundSlideshow,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'fullscreen',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/BackgroundSlideshow',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof BackgroundSlideshow>;
|
|
15
|
+
|
|
16
|
+
const sampleImages: ImageData[] = [
|
|
17
|
+
{
|
|
18
|
+
at: { de: 'Bild 1', en: 'Image 1' },
|
|
19
|
+
fn: 'image1.jpg',
|
|
20
|
+
hu: 200,
|
|
21
|
+
id: '1',
|
|
22
|
+
po: false,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
at: { de: 'Bild 2', en: 'Image 2' },
|
|
26
|
+
fn: 'image2.jpg',
|
|
27
|
+
hu: 150,
|
|
28
|
+
id: '2',
|
|
29
|
+
po: false,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
at: { de: 'Bild 3', en: 'Image 3' },
|
|
33
|
+
fn: 'image3.jpg',
|
|
34
|
+
hu: 100,
|
|
35
|
+
id: '3',
|
|
36
|
+
po: false,
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
export const Default: Story = {
|
|
41
|
+
args: {
|
|
42
|
+
baseUrl: 'https://via.placeholder.com/{format}?text=Image+{id}',
|
|
43
|
+
className: 'h-[400px] w-full',
|
|
44
|
+
images: sampleImages,
|
|
45
|
+
locale: 'en',
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const WithoutSlideshow: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
baseUrl: 'https://via.placeholder.com/{format}?text=Static',
|
|
52
|
+
className: 'h-[400px] w-full',
|
|
53
|
+
images: sampleImages,
|
|
54
|
+
locale: 'en',
|
|
55
|
+
slideshow: false,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const FastTransition: Story = {
|
|
60
|
+
args: {
|
|
61
|
+
baseUrl: 'https://via.placeholder.com/{format}?text=Fast',
|
|
62
|
+
className: 'h-[400px] w-full',
|
|
63
|
+
images: sampleImages,
|
|
64
|
+
locale: 'en',
|
|
65
|
+
slideshowInterval: 2000,
|
|
66
|
+
transitionDuration: 1000,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { BlurryGradient } from '../components/blurry-gradient';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof BlurryGradient> = {
|
|
5
|
+
component: BlurryGradient,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'centered',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
title: 'Components/BlurryGradient',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof BlurryGradient>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
neutralColor: '#f0f0f0',
|
|
19
|
+
primaryColor: '#3b82f6',
|
|
20
|
+
secondaryColor: '#8b5cf6',
|
|
21
|
+
style: { height: '400px', width: '400px' },
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const WarmColors: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
neutralColor: '#fef3c7',
|
|
28
|
+
primaryColor: '#f97316',
|
|
29
|
+
secondaryColor: '#ef4444',
|
|
30
|
+
style: { height: '400px', width: '400px' },
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const CoolColors: Story = {
|
|
35
|
+
args: {
|
|
36
|
+
neutralColor: '#e0f2fe',
|
|
37
|
+
primaryColor: '#0ea5e9',
|
|
38
|
+
secondaryColor: '#06b6d4',
|
|
39
|
+
style: { height: '400px', width: '400px' },
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const NatureColors: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
neutralColor: '#fef9c3',
|
|
46
|
+
primaryColor: '#22c55e',
|
|
47
|
+
secondaryColor: '#84cc16',
|
|
48
|
+
style: { height: '400px', width: '400px' },
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const FullWidth: Story = {
|
|
53
|
+
args: {
|
|
54
|
+
neutralColor: '#f0f0f0',
|
|
55
|
+
primaryColor: '#3b82f6',
|
|
56
|
+
secondaryColor: '#8b5cf6',
|
|
57
|
+
style: { height: '200px', width: '100%' },
|
|
58
|
+
},
|
|
59
|
+
parameters: {
|
|
60
|
+
layout: 'fullscreen',
|
|
61
|
+
},
|
|
62
|
+
};
|