@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.
Files changed (404) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +133 -0
  3. package/dist/components/background-slideshow.d.ts +22 -0
  4. package/dist/components/background-slideshow.d.ts.map +1 -0
  5. package/dist/components/background-slideshow.js +76 -0
  6. package/dist/components/blurry-gradient.d.ts +9 -0
  7. package/dist/components/blurry-gradient.d.ts.map +1 -0
  8. package/dist/components/blurry-gradient.js +6 -0
  9. package/dist/components/box.d.ts +17 -0
  10. package/dist/components/box.d.ts.map +1 -0
  11. package/dist/components/box.js +25 -0
  12. package/dist/components/carousel.d.ts +26 -0
  13. package/dist/components/carousel.d.ts.map +1 -0
  14. package/dist/components/carousel.js +87 -0
  15. package/dist/components/countdown.d.ts +2 -0
  16. package/dist/components/countdown.d.ts.map +1 -0
  17. package/dist/components/countdown.js +48 -0
  18. package/dist/components/definition-list.d.ts +40 -0
  19. package/dist/components/definition-list.d.ts.map +1 -0
  20. package/dist/components/definition-list.js +57 -0
  21. package/dist/components/generic-error.d.ts +23 -0
  22. package/dist/components/generic-error.d.ts.map +1 -0
  23. package/dist/components/generic-error.js +39 -0
  24. package/dist/components/heading.d.ts +24 -0
  25. package/dist/components/heading.d.ts.map +1 -0
  26. package/dist/components/heading.js +29 -0
  27. package/dist/components/highlight.d.ts +16 -0
  28. package/dist/components/highlight.d.ts.map +1 -0
  29. package/dist/components/highlight.js +19 -0
  30. package/dist/components/icon-button.d.ts +6 -0
  31. package/dist/components/icon-button.d.ts.map +1 -0
  32. package/dist/components/icon-button.js +6 -0
  33. package/dist/components/if.d.ts +8 -0
  34. package/dist/components/if.d.ts.map +1 -0
  35. package/dist/components/if.js +16 -0
  36. package/dist/components/iframe.d.ts +8 -0
  37. package/dist/components/iframe.d.ts.map +1 -0
  38. package/dist/components/iframe.js +3 -0
  39. package/dist/components/item.d.ts +67 -0
  40. package/dist/components/item.d.ts.map +1 -0
  41. package/dist/components/item.js +309 -0
  42. package/dist/components/leaflet-map.d.ts +33 -0
  43. package/dist/components/leaflet-map.d.ts.map +1 -0
  44. package/dist/components/leaflet-map.js +195 -0
  45. package/dist/components/link.d.ts +41 -0
  46. package/dist/components/link.d.ts.map +1 -0
  47. package/dist/components/link.js +111 -0
  48. package/dist/components/link.test.d.ts +2 -0
  49. package/dist/components/link.test.d.ts.map +1 -0
  50. package/dist/components/link.test.js +204 -0
  51. package/dist/components/list-item.d.ts +16 -0
  52. package/dist/components/list-item.d.ts.map +1 -0
  53. package/dist/components/list-item.js +19 -0
  54. package/dist/components/maptiler-map.d.ts +26 -0
  55. package/dist/components/maptiler-map.d.ts.map +1 -0
  56. package/dist/components/maptiler-map.js +116 -0
  57. package/dist/components/markdown-container.d.ts +20 -0
  58. package/dist/components/markdown-container.d.ts.map +1 -0
  59. package/dist/components/markdown-container.js +93 -0
  60. package/dist/components/password-input.d.ts +9 -0
  61. package/dist/components/password-input.d.ts.map +1 -0
  62. package/dist/components/password-input.js +13 -0
  63. package/dist/components/picture.d.ts +26 -0
  64. package/dist/components/picture.d.ts.map +1 -0
  65. package/dist/components/picture.js +36 -0
  66. package/dist/components/protected-email.d.ts +9 -0
  67. package/dist/components/protected-email.d.ts.map +1 -0
  68. package/dist/components/protected-email.js +16 -0
  69. package/dist/components/text.d.ts +17 -0
  70. package/dist/components/text.d.ts.map +1 -0
  71. package/dist/components/text.js +27 -0
  72. package/dist/components/unordered-list.d.ts +16 -0
  73. package/dist/components/unordered-list.d.ts.map +1 -0
  74. package/dist/components/unordered-list.js +21 -0
  75. package/dist/hooks/use-current-route-data.d.ts +2 -0
  76. package/dist/hooks/use-current-route-data.d.ts.map +1 -0
  77. package/dist/hooks/use-current-route-data.js +12 -0
  78. package/dist/hooks/use-focus-search.d.ts +3 -0
  79. package/dist/hooks/use-focus-search.d.ts.map +1 -0
  80. package/dist/hooks/use-focus-search.js +15 -0
  81. package/dist/hooks/use-matches-data.d.ts +2 -0
  82. package/dist/hooks/use-matches-data.d.ts.map +1 -0
  83. package/dist/hooks/use-matches-data.js +11 -0
  84. package/dist/hooks/use-media-query.d.ts +2 -0
  85. package/dist/hooks/use-media-query.d.ts.map +1 -0
  86. package/dist/hooks/use-media-query.js +16 -0
  87. package/dist/hooks/use-mobile.d.ts +2 -0
  88. package/dist/hooks/use-mobile.d.ts.map +1 -0
  89. package/dist/hooks/use-mobile.js +15 -0
  90. package/dist/hooks/use-nonce.d.ts +5 -0
  91. package/dist/hooks/use-nonce.d.ts.map +1 -0
  92. package/dist/hooks/use-nonce.js +9 -0
  93. package/dist/hooks/use-nonce.test.d.ts +2 -0
  94. package/dist/hooks/use-nonce.test.d.ts.map +1 -0
  95. package/dist/hooks/use-nonce.test.js +27 -0
  96. package/dist/hooks/use-orientation.d.ts +3 -0
  97. package/dist/hooks/use-orientation.d.ts.map +1 -0
  98. package/dist/hooks/use-orientation.js +25 -0
  99. package/dist/hooks/use-user.d.ts +15 -0
  100. package/dist/hooks/use-user.d.ts.map +1 -0
  101. package/dist/hooks/use-user.js +17 -0
  102. package/dist/shadcn/accordion.d.ts +25 -0
  103. package/dist/shadcn/accordion.d.ts.map +1 -0
  104. package/dist/shadcn/accordion.js +45 -0
  105. package/dist/shadcn/alert-dialog.d.ts +73 -0
  106. package/dist/shadcn/alert-dialog.d.ts.map +1 -0
  107. package/dist/shadcn/alert-dialog.js +93 -0
  108. package/dist/shadcn/alert.d.ts +34 -0
  109. package/dist/shadcn/alert.d.ts.map +1 -0
  110. package/dist/shadcn/alert.js +42 -0
  111. package/dist/shadcn/aspect-ratio.d.ts +6 -0
  112. package/dist/shadcn/aspect-ratio.d.ts.map +1 -0
  113. package/dist/shadcn/aspect-ratio.js +7 -0
  114. package/dist/shadcn/avatar.d.ts +16 -0
  115. package/dist/shadcn/avatar.d.ts.map +1 -0
  116. package/dist/shadcn/avatar.js +27 -0
  117. package/dist/shadcn/badge.d.ts +29 -0
  118. package/dist/shadcn/badge.d.ts.map +1 -0
  119. package/dist/shadcn/badge.js +29 -0
  120. package/dist/shadcn/breadcrumb.d.ts +42 -0
  121. package/dist/shadcn/breadcrumb.d.ts.map +1 -0
  122. package/dist/shadcn/breadcrumb.js +74 -0
  123. package/dist/shadcn/button.d.ts +38 -0
  124. package/dist/shadcn/button.d.ts.map +1 -0
  125. package/dist/shadcn/button.js +38 -0
  126. package/dist/shadcn/calendar.d.ts +23 -0
  127. package/dist/shadcn/calendar.d.ts.map +1 -0
  128. package/dist/shadcn/calendar.js +163 -0
  129. package/dist/shadcn/card.d.ts +31 -0
  130. package/dist/shadcn/card.d.ts.map +1 -0
  131. package/dist/shadcn/card.js +55 -0
  132. package/dist/shadcn/carousel.d.ts +51 -0
  133. package/dist/shadcn/carousel.d.ts.map +1 -0
  134. package/dist/shadcn/carousel.js +161 -0
  135. package/dist/shadcn/chart.d.ts +103 -0
  136. package/dist/shadcn/chart.d.ts.map +1 -0
  137. package/dist/shadcn/chart.js +248 -0
  138. package/dist/shadcn/checkbox.d.ts +8 -0
  139. package/dist/shadcn/checkbox.d.ts.map +1 -0
  140. package/dist/shadcn/checkbox.js +22 -0
  141. package/dist/shadcn/collapsible.d.ts +16 -0
  142. package/dist/shadcn/collapsible.d.ts.map +1 -0
  143. package/dist/shadcn/collapsible.js +19 -0
  144. package/dist/shadcn/command.d.ts +61 -0
  145. package/dist/shadcn/command.d.ts.map +1 -0
  146. package/dist/shadcn/command.js +123 -0
  147. package/dist/shadcn/context-menu.d.ts +107 -0
  148. package/dist/shadcn/context-menu.d.ts.map +1 -0
  149. package/dist/shadcn/context-menu.js +151 -0
  150. package/dist/shadcn/dialog.d.ts +57 -0
  151. package/dist/shadcn/dialog.d.ts.map +1 -0
  152. package/dist/shadcn/dialog.js +96 -0
  153. package/dist/shadcn/drawer.d.ts +54 -0
  154. package/dist/shadcn/drawer.d.ts.map +1 -0
  155. package/dist/shadcn/drawer.js +96 -0
  156. package/dist/shadcn/dropdown-menu.d.ts +110 -0
  157. package/dist/shadcn/dropdown-menu.d.ts.map +1 -0
  158. package/dist/shadcn/dropdown-menu.js +152 -0
  159. package/dist/shadcn/form.d.ts +59 -0
  160. package/dist/shadcn/form.d.ts.map +1 -0
  161. package/dist/shadcn/form.js +99 -0
  162. package/dist/shadcn/hover-card.d.ts +20 -0
  163. package/dist/shadcn/hover-card.d.ts.map +1 -0
  164. package/dist/shadcn/hover-card.js +26 -0
  165. package/dist/shadcn/input-otp.d.ts +25 -0
  166. package/dist/shadcn/input-otp.d.ts.map +1 -0
  167. package/dist/shadcn/input-otp.js +54 -0
  168. package/dist/shadcn/input.d.ts +14 -0
  169. package/dist/shadcn/input.d.ts.map +1 -0
  170. package/dist/shadcn/input.js +48 -0
  171. package/dist/shadcn/label.d.ts +8 -0
  172. package/dist/shadcn/label.d.ts.map +1 -0
  173. package/dist/shadcn/label.js +16 -0
  174. package/dist/shadcn/menubar.d.ts +108 -0
  175. package/dist/shadcn/menubar.d.ts.map +1 -0
  176. package/dist/shadcn/menubar.js +174 -0
  177. package/dist/shadcn/navigation-menu.d.ts +79 -0
  178. package/dist/shadcn/navigation-menu.d.ts.map +1 -0
  179. package/dist/shadcn/navigation-menu.js +108 -0
  180. package/dist/shadcn/pagination.d.ts +45 -0
  181. package/dist/shadcn/pagination.d.ts.map +1 -0
  182. package/dist/shadcn/pagination.js +83 -0
  183. package/dist/shadcn/popover.d.ts +19 -0
  184. package/dist/shadcn/popover.d.ts.map +1 -0
  185. package/dist/shadcn/popover.js +29 -0
  186. package/dist/shadcn/progress.d.ts +9 -0
  187. package/dist/shadcn/progress.d.ts.map +1 -0
  188. package/dist/shadcn/progress.js +17 -0
  189. package/dist/shadcn/radio-group.d.ts +12 -0
  190. package/dist/shadcn/radio-group.d.ts.map +1 -0
  191. package/dist/shadcn/radio-group.js +32 -0
  192. package/dist/shadcn/resizable.d.ts +20 -0
  193. package/dist/shadcn/resizable.d.ts.map +1 -0
  194. package/dist/shadcn/resizable.js +32 -0
  195. package/dist/shadcn/scroll-area.d.ts +16 -0
  196. package/dist/shadcn/scroll-area.d.ts.map +1 -0
  197. package/dist/shadcn/scroll-area.js +40 -0
  198. package/dist/shadcn/select.d.ts +63 -0
  199. package/dist/shadcn/select.d.ts.map +1 -0
  200. package/dist/shadcn/select.js +120 -0
  201. package/dist/shadcn/separator.d.ts +10 -0
  202. package/dist/shadcn/separator.d.ts.map +1 -0
  203. package/dist/shadcn/separator.js +18 -0
  204. package/dist/shadcn/sheet.d.ts +48 -0
  205. package/dist/shadcn/sheet.d.ts.map +1 -0
  206. package/dist/shadcn/sheet.js +99 -0
  207. package/dist/shadcn/sidebar.d.ts +200 -0
  208. package/dist/shadcn/sidebar.d.ts.map +1 -0
  209. package/dist/shadcn/sidebar.js +528 -0
  210. package/dist/shadcn/skeleton.d.ts +6 -0
  211. package/dist/shadcn/skeleton.d.ts.map +1 -0
  212. package/dist/shadcn/skeleton.js +11 -0
  213. package/dist/shadcn/slider.d.ts +12 -0
  214. package/dist/shadcn/slider.d.ts.map +1 -0
  215. package/dist/shadcn/slider.js +50 -0
  216. package/dist/shadcn/sonner.d.ts +7 -0
  217. package/dist/shadcn/sonner.d.ts.map +1 -0
  218. package/dist/shadcn/sonner.js +20 -0
  219. package/dist/shadcn/switch.d.ts +8 -0
  220. package/dist/shadcn/switch.d.ts.map +1 -0
  221. package/dist/shadcn/switch.js +22 -0
  222. package/dist/shadcn/table.d.ts +35 -0
  223. package/dist/shadcn/table.d.ts.map +1 -0
  224. package/dist/shadcn/table.js +73 -0
  225. package/dist/shadcn/tabs.d.ts +20 -0
  226. package/dist/shadcn/tabs.d.ts.map +1 -0
  227. package/dist/shadcn/tabs.js +40 -0
  228. package/dist/shadcn/textarea.d.ts +7 -0
  229. package/dist/shadcn/textarea.d.ts.map +1 -0
  230. package/dist/shadcn/textarea.js +14 -0
  231. package/dist/shadcn/toggle-group.d.ts +22 -0
  232. package/dist/shadcn/toggle-group.d.ts.map +1 -0
  233. package/dist/shadcn/toggle-group.js +43 -0
  234. package/dist/shadcn/toggle.d.ts +29 -0
  235. package/dist/shadcn/toggle.d.ts.map +1 -0
  236. package/dist/shadcn/toggle.js +31 -0
  237. package/dist/shadcn/tooltip.d.ts +20 -0
  238. package/dist/shadcn/tooltip.d.ts.map +1 -0
  239. package/dist/shadcn/tooltip.js +40 -0
  240. package/dist/stories/BackgroundSlideshow.stories.d.ts +9 -0
  241. package/dist/stories/BackgroundSlideshow.stories.d.ts.map +1 -0
  242. package/dist/stories/BackgroundSlideshow.stories.js +60 -0
  243. package/dist/stories/BlurryGradient.stories.d.ts +11 -0
  244. package/dist/stories/BlurryGradient.stories.d.ts.map +1 -0
  245. package/dist/stories/BlurryGradient.stories.js +53 -0
  246. package/dist/stories/Box.stories.d.ts +13 -0
  247. package/dist/stories/Box.stories.d.ts.map +1 -0
  248. package/dist/stories/Box.stories.js +50 -0
  249. package/dist/stories/Carousel.stories.d.ts +9 -0
  250. package/dist/stories/Carousel.stories.d.ts.map +1 -0
  251. package/dist/stories/Carousel.stories.js +30 -0
  252. package/dist/stories/Countdown.stories.d.ts +7 -0
  253. package/dist/stories/Countdown.stories.d.ts.map +1 -0
  254. package/dist/stories/Countdown.stories.js +11 -0
  255. package/dist/stories/DefinitionList.stories.d.ts +9 -0
  256. package/dist/stories/DefinitionList.stories.d.ts.map +1 -0
  257. package/dist/stories/DefinitionList.stories.js +20 -0
  258. package/dist/stories/GenericError.stories.d.ts +9 -0
  259. package/dist/stories/GenericError.stories.d.ts.map +1 -0
  260. package/dist/stories/GenericError.stories.js +39 -0
  261. package/dist/stories/Heading.stories.d.ts +15 -0
  262. package/dist/stories/Heading.stories.d.ts.map +1 -0
  263. package/dist/stories/Heading.stories.js +61 -0
  264. package/dist/stories/Highlight.stories.d.ts +8 -0
  265. package/dist/stories/Highlight.stories.d.ts.map +1 -0
  266. package/dist/stories/Highlight.stories.js +19 -0
  267. package/dist/stories/IconButton.stories.d.ts +10 -0
  268. package/dist/stories/IconButton.stories.d.ts.map +1 -0
  269. package/dist/stories/IconButton.stories.js +32 -0
  270. package/dist/stories/If.stories.d.ts +13 -0
  271. package/dist/stories/If.stories.d.ts.map +1 -0
  272. package/dist/stories/If.stories.js +54 -0
  273. package/dist/stories/Iframe.stories.d.ts +8 -0
  274. package/dist/stories/Iframe.stories.d.ts.map +1 -0
  275. package/dist/stories/Iframe.stories.js +23 -0
  276. package/dist/stories/Item.stories.d.ts +10 -0
  277. package/dist/stories/Item.stories.d.ts.map +1 -0
  278. package/dist/stories/Item.stories.js +32 -0
  279. package/dist/stories/Link.stories.d.ts +10 -0
  280. package/dist/stories/Link.stories.d.ts.map +1 -0
  281. package/dist/stories/Link.stories.js +36 -0
  282. package/dist/stories/ListItem.stories.d.ts +9 -0
  283. package/dist/stories/ListItem.stories.d.ts.map +1 -0
  284. package/dist/stories/ListItem.stories.js +25 -0
  285. package/dist/stories/MarkdownContainer.stories.d.ts +11 -0
  286. package/dist/stories/MarkdownContainer.stories.d.ts.map +1 -0
  287. package/dist/stories/MarkdownContainer.stories.js +66 -0
  288. package/dist/stories/PasswordInput.stories.d.ts +9 -0
  289. package/dist/stories/PasswordInput.stories.d.ts.map +1 -0
  290. package/dist/stories/PasswordInput.stories.js +27 -0
  291. package/dist/stories/Picture.stories.d.ts +10 -0
  292. package/dist/stories/Picture.stories.d.ts.map +1 -0
  293. package/dist/stories/Picture.stories.js +46 -0
  294. package/dist/stories/ProtectedEmail.stories.d.ts +10 -0
  295. package/dist/stories/ProtectedEmail.stories.d.ts.map +1 -0
  296. package/dist/stories/ProtectedEmail.stories.js +34 -0
  297. package/dist/stories/Text.stories.d.ts +10 -0
  298. package/dist/stories/Text.stories.d.ts.map +1 -0
  299. package/dist/stories/Text.stories.js +31 -0
  300. package/dist/stories/UnorderedList.stories.d.ts +10 -0
  301. package/dist/stories/UnorderedList.stories.d.ts.map +1 -0
  302. package/dist/stories/UnorderedList.stories.js +24 -0
  303. package/dist/test-setup.d.ts +2 -0
  304. package/dist/test-setup.d.ts.map +1 -0
  305. package/dist/test-setup.js +1 -0
  306. package/dist/utils/author.d.ts +9 -0
  307. package/dist/utils/author.d.ts.map +1 -0
  308. package/dist/utils/author.js +37 -0
  309. package/dist/utils/author.test.d.ts +2 -0
  310. package/dist/utils/author.test.d.ts.map +1 -0
  311. package/dist/utils/author.test.js +46 -0
  312. package/dist/utils/cn.d.ts +5 -0
  313. package/dist/utils/cn.d.ts.map +1 -0
  314. package/dist/utils/cn.js +10 -0
  315. package/dist/utils/cn.test.d.ts +2 -0
  316. package/dist/utils/cn.test.d.ts.map +1 -0
  317. package/dist/utils/cn.test.js +33 -0
  318. package/dist/utils/is-route-active.d.ts +3 -0
  319. package/dist/utils/is-route-active.d.ts.map +1 -0
  320. package/dist/utils/is-route-active.js +54 -0
  321. package/dist/utils/is-route-active.test.d.ts +2 -0
  322. package/dist/utils/is-route-active.test.d.ts.map +1 -0
  323. package/dist/utils/is-route-active.test.js +61 -0
  324. package/dist/utils/locale.d.ts +22 -0
  325. package/dist/utils/locale.d.ts.map +1 -0
  326. package/dist/utils/locale.js +25 -0
  327. package/dist/utils/locale.test.d.ts +2 -0
  328. package/dist/utils/locale.test.d.ts.map +1 -0
  329. package/dist/utils/locale.test.js +99 -0
  330. package/dist/utils/text.d.ts +7 -0
  331. package/dist/utils/text.d.ts.map +1 -0
  332. package/dist/utils/text.js +102 -0
  333. package/dist/utils/text.test.d.ts +2 -0
  334. package/dist/utils/text.test.d.ts.map +1 -0
  335. package/dist/utils/text.test.js +122 -0
  336. package/package.json +117 -0
  337. package/src/components/background-slideshow.tsx +172 -0
  338. package/src/components/blurry-gradient.tsx +97 -0
  339. package/src/components/box.tsx +45 -0
  340. package/src/components/carousel.tsx +197 -0
  341. package/src/components/countdown.tsx +82 -0
  342. package/src/components/definition-list.tsx +90 -0
  343. package/src/components/generic-error.tsx +104 -0
  344. package/src/components/heading.tsx +60 -0
  345. package/src/components/highlight.tsx +53 -0
  346. package/src/components/icon-button.tsx +20 -0
  347. package/src/components/if.tsx +29 -0
  348. package/src/components/iframe.tsx +19 -0
  349. package/src/components/item.tsx +340 -0
  350. package/src/components/leaflet-map.tsx +294 -0
  351. package/src/components/link.test.tsx +387 -0
  352. package/src/components/link.tsx +206 -0
  353. package/src/components/list-item.tsx +30 -0
  354. package/src/components/maptiler-map.tsx +181 -0
  355. package/src/components/markdown-container.tsx +153 -0
  356. package/src/components/password-input.tsx +49 -0
  357. package/src/components/picture.tsx +107 -0
  358. package/src/components/protected-email.tsx +49 -0
  359. package/src/components/text.tsx +38 -0
  360. package/src/components/unordered-list.tsx +32 -0
  361. package/src/hooks/use-current-route-data.ts +18 -0
  362. package/src/hooks/use-focus-search.ts +20 -0
  363. package/src/hooks/use-matches-data.ts +19 -0
  364. package/src/hooks/use-media-query.ts +33 -0
  365. package/src/hooks/use-mobile.ts +19 -0
  366. package/src/hooks/use-nonce.test.ts +35 -0
  367. package/src/hooks/use-nonce.ts +20 -0
  368. package/src/hooks/use-orientation.ts +48 -0
  369. package/src/hooks/use-user.tsx +72 -0
  370. package/src/stories/BackgroundSlideshow.stories.tsx +68 -0
  371. package/src/stories/BlurryGradient.stories.tsx +62 -0
  372. package/src/stories/Box.stories.tsx +83 -0
  373. package/src/stories/Carousel.stories.tsx +95 -0
  374. package/src/stories/Countdown.stories.tsx +16 -0
  375. package/src/stories/DefinitionList.stories.tsx +51 -0
  376. package/src/stories/GenericError.stories.tsx +58 -0
  377. package/src/stories/Heading.stories.tsx +82 -0
  378. package/src/stories/Highlight.stories.tsx +28 -0
  379. package/src/stories/IconButton.stories.tsx +90 -0
  380. package/src/stories/If.stories.tsx +72 -0
  381. package/src/stories/Iframe.stories.tsx +29 -0
  382. package/src/stories/Item.stories.tsx +79 -0
  383. package/src/stories/Link.stories.tsx +58 -0
  384. package/src/stories/ListItem.stories.tsx +37 -0
  385. package/src/stories/MarkdownContainer.stories.tsx +76 -0
  386. package/src/stories/PasswordInput.stories.tsx +34 -0
  387. package/src/stories/Picture.stories.tsx +54 -0
  388. package/src/stories/ProtectedEmail.stories.tsx +57 -0
  389. package/src/stories/Text.stories.tsx +44 -0
  390. package/src/stories/UnorderedList.stories.tsx +73 -0
  391. package/src/styles/storybook.css +1 -0
  392. package/src/styles/tailwind.css +7 -0
  393. package/src/test-setup.ts +1 -0
  394. package/src/utils/author.test.ts +54 -0
  395. package/src/utils/author.tsx +73 -0
  396. package/src/utils/cn.test.ts +48 -0
  397. package/src/utils/cn.ts +14 -0
  398. package/src/utils/is-route-active.test.ts +80 -0
  399. package/src/utils/is-route-active.ts +100 -0
  400. package/src/utils/locale.test.ts +148 -0
  401. package/src/utils/locale.ts +127 -0
  402. package/src/utils/text.test.ts +152 -0
  403. package/src/utils/text.tsx +209 -0
  404. 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
+ };