@beautinique/frontend-components 1.0.7 → 1.0.9

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 (472) hide show
  1. package/README.md +389 -14
  2. package/dist/auth/AuthBottomInstructions.d.cts +42 -0
  3. package/dist/auth/AuthBottomInstructions.d.cts.map +1 -0
  4. package/dist/auth/AuthBottomInstructions.d.ts +42 -0
  5. package/dist/auth/AuthBottomInstructions.d.ts.map +1 -0
  6. package/dist/auth/SocialAuth.d.cts +33 -0
  7. package/dist/auth/SocialAuth.d.cts.map +1 -0
  8. package/dist/auth/SocialAuth.d.ts +33 -0
  9. package/dist/auth/SocialAuth.d.ts.map +1 -0
  10. package/dist/auth/index.cjs +84 -0
  11. package/dist/auth/index.cjs.map +1 -0
  12. package/dist/auth/index.d.cts +3 -0
  13. package/dist/auth/index.d.cts.map +1 -0
  14. package/dist/auth/index.d.ts +3 -0
  15. package/dist/auth/index.d.ts.map +1 -0
  16. package/dist/auth/index.js +81 -0
  17. package/dist/auth/index.js.map +1 -0
  18. package/dist/breadcrumb/Breadcrumb.d.cts +34 -0
  19. package/dist/breadcrumb/Breadcrumb.d.cts.map +1 -0
  20. package/dist/breadcrumb/Breadcrumb.d.ts +34 -0
  21. package/dist/breadcrumb/Breadcrumb.d.ts.map +1 -0
  22. package/dist/breadcrumb/breadcrumb-icons.d.cts +6 -0
  23. package/dist/breadcrumb/breadcrumb-icons.d.cts.map +1 -0
  24. package/dist/breadcrumb/breadcrumb-icons.d.ts +6 -0
  25. package/dist/breadcrumb/breadcrumb-icons.d.ts.map +1 -0
  26. package/dist/breadcrumb/getBreadcrumbItems.d.cts +16 -0
  27. package/dist/breadcrumb/getBreadcrumbItems.d.cts.map +1 -0
  28. package/dist/breadcrumb/getBreadcrumbItems.d.ts +16 -0
  29. package/dist/breadcrumb/getBreadcrumbItems.d.ts.map +1 -0
  30. package/dist/breadcrumb/index.cjs +110 -0
  31. package/dist/breadcrumb/index.cjs.map +1 -0
  32. package/dist/breadcrumb/index.d.cts +3 -0
  33. package/dist/breadcrumb/index.d.cts.map +1 -0
  34. package/dist/breadcrumb/index.d.ts +3 -0
  35. package/dist/breadcrumb/index.d.ts.map +1 -0
  36. package/dist/breadcrumb/index.js +107 -0
  37. package/dist/breadcrumb/index.js.map +1 -0
  38. package/dist/color-input/ColorInput.d.cts +33 -0
  39. package/dist/color-input/ColorInput.d.cts.map +1 -0
  40. package/dist/color-input/ColorInput.d.ts +33 -0
  41. package/dist/color-input/ColorInput.d.ts.map +1 -0
  42. package/dist/color-input/color-input-icons.d.cts +6 -0
  43. package/dist/color-input/color-input-icons.d.cts.map +1 -0
  44. package/dist/color-input/color-input-icons.d.ts +6 -0
  45. package/dist/color-input/color-input-icons.d.ts.map +1 -0
  46. package/dist/color-input/color.d.cts +10 -0
  47. package/dist/color-input/color.d.cts.map +1 -0
  48. package/dist/color-input/color.d.ts +10 -0
  49. package/dist/color-input/color.d.ts.map +1 -0
  50. package/dist/color-input/index.cjs +375 -0
  51. package/dist/color-input/index.cjs.map +1 -0
  52. package/dist/color-input/index.d.cts +2 -0
  53. package/dist/color-input/index.d.cts.map +1 -0
  54. package/dist/color-input/index.d.ts +2 -0
  55. package/dist/color-input/index.d.ts.map +1 -0
  56. package/dist/color-input/index.js +373 -0
  57. package/dist/color-input/index.js.map +1 -0
  58. package/dist/file-input/FileInput.d.cts +53 -0
  59. package/dist/file-input/FileInput.d.cts.map +1 -0
  60. package/dist/file-input/FileInput.d.ts +53 -0
  61. package/dist/file-input/FileInput.d.ts.map +1 -0
  62. package/dist/file-input/file-input-icons.d.cts +6 -0
  63. package/dist/file-input/file-input-icons.d.cts.map +1 -0
  64. package/dist/file-input/file-input-icons.d.ts +6 -0
  65. package/dist/file-input/file-input-icons.d.ts.map +1 -0
  66. package/dist/file-input/index.cjs +259 -0
  67. package/dist/file-input/index.cjs.map +1 -0
  68. package/dist/file-input/index.d.cts +3 -0
  69. package/dist/file-input/index.d.cts.map +1 -0
  70. package/dist/file-input/index.d.ts +3 -0
  71. package/dist/file-input/index.d.ts.map +1 -0
  72. package/dist/file-input/index.js +256 -0
  73. package/dist/file-input/index.js.map +1 -0
  74. package/dist/file-input/media-type.d.cts +8 -0
  75. package/dist/file-input/media-type.d.cts.map +1 -0
  76. package/dist/file-input/media-type.d.ts +8 -0
  77. package/dist/file-input/media-type.d.ts.map +1 -0
  78. package/dist/file-input/useObjectUrls.d.cts +10 -0
  79. package/dist/file-input/useObjectUrls.d.cts.map +1 -0
  80. package/dist/file-input/useObjectUrls.d.ts +10 -0
  81. package/dist/file-input/useObjectUrls.d.ts.map +1 -0
  82. package/dist/hierarchy-select/HierarchySelect.d.cts +58 -0
  83. package/dist/hierarchy-select/HierarchySelect.d.cts.map +1 -0
  84. package/dist/hierarchy-select/HierarchySelect.d.ts +58 -0
  85. package/dist/hierarchy-select/HierarchySelect.d.ts.map +1 -0
  86. package/dist/hierarchy-select/hierarchy-select-icons.d.cts +6 -0
  87. package/dist/hierarchy-select/hierarchy-select-icons.d.cts.map +1 -0
  88. package/dist/hierarchy-select/hierarchy-select-icons.d.ts +6 -0
  89. package/dist/hierarchy-select/hierarchy-select-icons.d.ts.map +1 -0
  90. package/dist/hierarchy-select/index.cjs +596 -0
  91. package/dist/hierarchy-select/index.cjs.map +1 -0
  92. package/dist/hierarchy-select/index.d.cts +2 -0
  93. package/dist/hierarchy-select/index.d.cts.map +1 -0
  94. package/dist/hierarchy-select/index.d.ts +2 -0
  95. package/dist/hierarchy-select/index.d.ts.map +1 -0
  96. package/dist/hierarchy-select/index.js +594 -0
  97. package/dist/hierarchy-select/index.js.map +1 -0
  98. package/dist/hierarchy-select/tree.d.cts +38 -0
  99. package/dist/hierarchy-select/tree.d.cts.map +1 -0
  100. package/dist/hierarchy-select/tree.d.ts +38 -0
  101. package/dist/hierarchy-select/tree.d.ts.map +1 -0
  102. package/dist/index.cjs +21 -0
  103. package/dist/index.d.cts +3 -0
  104. package/dist/index.d.cts.map +1 -1
  105. package/dist/index.d.ts +3 -0
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +3 -0
  108. package/dist/inputs/Checkbox.d.cts +21 -0
  109. package/dist/inputs/Checkbox.d.cts.map +1 -0
  110. package/dist/inputs/Checkbox.d.ts +21 -0
  111. package/dist/inputs/Checkbox.d.ts.map +1 -0
  112. package/dist/inputs/Input.d.cts +26 -0
  113. package/dist/inputs/Input.d.cts.map +1 -0
  114. package/dist/inputs/Input.d.ts +26 -0
  115. package/dist/inputs/Input.d.ts.map +1 -0
  116. package/dist/inputs/InputError.d.cts +11 -0
  117. package/dist/inputs/InputError.d.cts.map +1 -0
  118. package/dist/inputs/InputError.d.ts +11 -0
  119. package/dist/inputs/InputError.d.ts.map +1 -0
  120. package/dist/inputs/InputIcon.d.cts +9 -0
  121. package/dist/inputs/InputIcon.d.cts.map +1 -0
  122. package/dist/inputs/InputIcon.d.ts +9 -0
  123. package/dist/inputs/InputIcon.d.ts.map +1 -0
  124. package/dist/inputs/InputLabel.d.cts +8 -0
  125. package/dist/inputs/InputLabel.d.cts.map +1 -0
  126. package/dist/inputs/InputLabel.d.ts +8 -0
  127. package/dist/inputs/InputLabel.d.ts.map +1 -0
  128. package/dist/inputs/Radio.d.cts +25 -0
  129. package/dist/inputs/Radio.d.cts.map +1 -0
  130. package/dist/inputs/Radio.d.ts +25 -0
  131. package/dist/inputs/Radio.d.ts.map +1 -0
  132. package/dist/inputs/Select.d.cts +53 -0
  133. package/dist/inputs/Select.d.cts.map +1 -0
  134. package/dist/inputs/Select.d.ts +53 -0
  135. package/dist/inputs/Select.d.ts.map +1 -0
  136. package/dist/inputs/Textarea.d.cts +19 -0
  137. package/dist/inputs/Textarea.d.cts.map +1 -0
  138. package/dist/inputs/Textarea.d.ts +19 -0
  139. package/dist/inputs/Textarea.d.ts.map +1 -0
  140. package/dist/inputs/index.cjs +746 -0
  141. package/dist/inputs/index.cjs.map +1 -0
  142. package/dist/inputs/index.d.cts +10 -0
  143. package/dist/inputs/index.d.cts.map +1 -0
  144. package/dist/inputs/index.d.ts +10 -0
  145. package/dist/inputs/index.d.ts.map +1 -0
  146. package/dist/inputs/index.js +737 -0
  147. package/dist/inputs/index.js.map +1 -0
  148. package/dist/inputs/inputs-icons.d.cts +6 -0
  149. package/dist/inputs/inputs-icons.d.cts.map +1 -0
  150. package/dist/inputs/inputs-icons.d.ts +6 -0
  151. package/dist/inputs/inputs-icons.d.ts.map +1 -0
  152. package/dist/inputs/types.d.cts +48 -0
  153. package/dist/inputs/types.d.cts.map +1 -0
  154. package/dist/inputs/types.d.ts +48 -0
  155. package/dist/inputs/types.d.ts.map +1 -0
  156. package/dist/inputs/useFieldIds.d.cts +24 -0
  157. package/dist/inputs/useFieldIds.d.cts.map +1 -0
  158. package/dist/inputs/useFieldIds.d.ts +24 -0
  159. package/dist/inputs/useFieldIds.d.ts.map +1 -0
  160. package/dist/layout/ApiStatus.d.cts +20 -0
  161. package/dist/layout/ApiStatus.d.cts.map +1 -0
  162. package/dist/layout/ApiStatus.d.ts +20 -0
  163. package/dist/layout/ApiStatus.d.ts.map +1 -0
  164. package/dist/layout/BorderGradient.d.cts +11 -0
  165. package/dist/layout/BorderGradient.d.cts.map +1 -0
  166. package/dist/layout/BorderGradient.d.ts +11 -0
  167. package/dist/layout/BorderGradient.d.ts.map +1 -0
  168. package/dist/layout/ConfirmModal.d.cts +44 -0
  169. package/dist/layout/ConfirmModal.d.cts.map +1 -0
  170. package/dist/layout/ConfirmModal.d.ts +44 -0
  171. package/dist/layout/ConfirmModal.d.ts.map +1 -0
  172. package/dist/layout/Dropdown.d.cts +33 -0
  173. package/dist/layout/Dropdown.d.cts.map +1 -0
  174. package/dist/layout/Dropdown.d.ts +33 -0
  175. package/dist/layout/Dropdown.d.ts.map +1 -0
  176. package/dist/layout/LoadingPage.d.cts +11 -0
  177. package/dist/layout/LoadingPage.d.cts.map +1 -0
  178. package/dist/layout/LoadingPage.d.ts +11 -0
  179. package/dist/layout/LoadingPage.d.ts.map +1 -0
  180. package/dist/layout/LoadingRings.d.cts +12 -0
  181. package/dist/layout/LoadingRings.d.cts.map +1 -0
  182. package/dist/layout/LoadingRings.d.ts +12 -0
  183. package/dist/layout/LoadingRings.d.ts.map +1 -0
  184. package/dist/layout/LoadingText.d.cts +13 -0
  185. package/dist/layout/LoadingText.d.cts.map +1 -0
  186. package/dist/layout/LoadingText.d.ts +13 -0
  187. package/dist/layout/LoadingText.d.ts.map +1 -0
  188. package/dist/layout/ModalWrapper.d.cts +48 -0
  189. package/dist/layout/ModalWrapper.d.cts.map +1 -0
  190. package/dist/layout/ModalWrapper.d.ts +48 -0
  191. package/dist/layout/ModalWrapper.d.ts.map +1 -0
  192. package/dist/layout/NetworkStatusToaster.d.cts +39 -0
  193. package/dist/layout/NetworkStatusToaster.d.cts.map +1 -0
  194. package/dist/layout/NetworkStatusToaster.d.ts +39 -0
  195. package/dist/layout/NetworkStatusToaster.d.ts.map +1 -0
  196. package/dist/layout/ScrollToTop.d.cts +36 -0
  197. package/dist/layout/ScrollToTop.d.cts.map +1 -0
  198. package/dist/layout/ScrollToTop.d.ts +36 -0
  199. package/dist/layout/ScrollToTop.d.ts.map +1 -0
  200. package/dist/layout/ScrollableGradientContainer.d.cts +28 -0
  201. package/dist/layout/ScrollableGradientContainer.d.cts.map +1 -0
  202. package/dist/layout/ScrollableGradientContainer.d.ts +28 -0
  203. package/dist/layout/ScrollableGradientContainer.d.ts.map +1 -0
  204. package/dist/layout/Skeleton.d.cts +9 -0
  205. package/dist/layout/Skeleton.d.cts.map +1 -0
  206. package/dist/layout/Skeleton.d.ts +9 -0
  207. package/dist/layout/Skeleton.d.ts.map +1 -0
  208. package/dist/layout/Table.d.cts +9 -0
  209. package/dist/layout/Table.d.cts.map +1 -0
  210. package/dist/layout/Table.d.ts +9 -0
  211. package/dist/layout/Table.d.ts.map +1 -0
  212. package/dist/layout/index.cjs +773 -0
  213. package/dist/layout/index.cjs.map +1 -0
  214. package/dist/layout/index.d.cts +14 -0
  215. package/dist/layout/index.d.cts.map +1 -0
  216. package/dist/layout/index.d.ts +14 -0
  217. package/dist/layout/index.d.ts.map +1 -0
  218. package/dist/layout/index.js +753 -0
  219. package/dist/layout/index.js.map +1 -0
  220. package/dist/layout/layout-icons.d.cts +6 -0
  221. package/dist/layout/layout-icons.d.cts.map +1 -0
  222. package/dist/layout/layout-icons.d.ts +6 -0
  223. package/dist/layout/layout-icons.d.ts.map +1 -0
  224. package/dist/lib/content.d.cts +7 -0
  225. package/dist/lib/content.d.cts.map +1 -0
  226. package/dist/lib/content.d.ts +7 -0
  227. package/dist/lib/content.d.ts.map +1 -0
  228. package/dist/lib/countdown.d.cts +13 -0
  229. package/dist/lib/countdown.d.cts.map +1 -0
  230. package/dist/lib/countdown.d.ts +13 -0
  231. package/dist/lib/countdown.d.ts.map +1 -0
  232. package/dist/lib/dropdown-position.d.cts +33 -0
  233. package/dist/lib/dropdown-position.d.cts.map +1 -0
  234. package/dist/lib/dropdown-position.d.ts +33 -0
  235. package/dist/lib/dropdown-position.d.ts.map +1 -0
  236. package/dist/lib/focus.d.cts +3 -0
  237. package/dist/lib/focus.d.cts.map +1 -0
  238. package/dist/lib/focus.d.ts +3 -0
  239. package/dist/lib/focus.d.ts.map +1 -0
  240. package/dist/lib/icon-registry.d.cts +14 -0
  241. package/dist/lib/icon-registry.d.cts.map +1 -0
  242. package/dist/lib/icon-registry.d.ts +14 -0
  243. package/dist/lib/icon-registry.d.ts.map +1 -0
  244. package/dist/lib/mergeRefs.d.cts +10 -0
  245. package/dist/lib/mergeRefs.d.cts.map +1 -0
  246. package/dist/lib/mergeRefs.d.ts +10 -0
  247. package/dist/lib/mergeRefs.d.ts.map +1 -0
  248. package/dist/lib/scrollRowIntoView.d.cts +7 -0
  249. package/dist/lib/scrollRowIntoView.d.cts.map +1 -0
  250. package/dist/lib/scrollRowIntoView.d.ts +7 -0
  251. package/dist/lib/scrollRowIntoView.d.ts.map +1 -0
  252. package/dist/lib/stepper.d.cts +9 -0
  253. package/dist/lib/stepper.d.cts.map +1 -0
  254. package/dist/lib/stepper.d.ts +9 -0
  255. package/dist/lib/stepper.d.ts.map +1 -0
  256. package/dist/lib/typeahead.d.cts +21 -0
  257. package/dist/lib/typeahead.d.cts.map +1 -0
  258. package/dist/lib/typeahead.d.ts +21 -0
  259. package/dist/lib/typeahead.d.ts.map +1 -0
  260. package/dist/lib/useAnchoredBox.d.cts +26 -0
  261. package/dist/lib/useAnchoredBox.d.cts.map +1 -0
  262. package/dist/lib/useAnchoredBox.d.ts +26 -0
  263. package/dist/lib/useAnchoredBox.d.ts.map +1 -0
  264. package/dist/lib/useDismiss.d.cts +34 -0
  265. package/dist/lib/useDismiss.d.cts.map +1 -0
  266. package/dist/lib/useDismiss.d.ts +34 -0
  267. package/dist/lib/useDismiss.d.ts.map +1 -0
  268. package/dist/lib/useFocusTrap.d.cts +24 -0
  269. package/dist/lib/useFocusTrap.d.cts.map +1 -0
  270. package/dist/lib/useFocusTrap.d.ts +24 -0
  271. package/dist/lib/useFocusTrap.d.ts.map +1 -0
  272. package/dist/lib/useIsClient.d.cts +7 -0
  273. package/dist/lib/useIsClient.d.cts.map +1 -0
  274. package/dist/lib/useIsClient.d.ts +7 -0
  275. package/dist/lib/useIsClient.d.ts.map +1 -0
  276. package/dist/lib/usePrefersReducedMotion.d.cts +7 -0
  277. package/dist/lib/usePrefersReducedMotion.d.cts.map +1 -0
  278. package/dist/lib/usePrefersReducedMotion.d.ts +7 -0
  279. package/dist/lib/usePrefersReducedMotion.d.ts.map +1 -0
  280. package/dist/lib/useScrollLock.d.cts +7 -0
  281. package/dist/lib/useScrollLock.d.cts.map +1 -0
  282. package/dist/lib/useScrollLock.d.ts +7 -0
  283. package/dist/lib/useScrollLock.d.ts.map +1 -0
  284. package/dist/lib/useScrollable.d.cts +17 -0
  285. package/dist/lib/useScrollable.d.cts.map +1 -0
  286. package/dist/lib/useScrollable.d.ts +17 -0
  287. package/dist/lib/useScrollable.d.ts.map +1 -0
  288. package/dist/linear-gradient/LinearGradient.d.cts +13 -0
  289. package/dist/linear-gradient/LinearGradient.d.cts.map +1 -0
  290. package/dist/linear-gradient/LinearGradient.d.ts +13 -0
  291. package/dist/linear-gradient/LinearGradient.d.ts.map +1 -0
  292. package/dist/linear-gradient/index.cjs +25 -0
  293. package/dist/linear-gradient/index.cjs.map +1 -0
  294. package/dist/linear-gradient/index.d.cts +2 -0
  295. package/dist/linear-gradient/index.d.cts.map +1 -0
  296. package/dist/linear-gradient/index.d.ts +2 -0
  297. package/dist/linear-gradient/index.d.ts.map +1 -0
  298. package/dist/linear-gradient/index.js +23 -0
  299. package/dist/linear-gradient/index.js.map +1 -0
  300. package/dist/loading-screen/LoadingScreen.d.cts +21 -0
  301. package/dist/loading-screen/LoadingScreen.d.cts.map +1 -0
  302. package/dist/loading-screen/LoadingScreen.d.ts +21 -0
  303. package/dist/loading-screen/LoadingScreen.d.ts.map +1 -0
  304. package/dist/loading-screen/Teddy.d.cts +10 -0
  305. package/dist/loading-screen/Teddy.d.cts.map +1 -0
  306. package/dist/loading-screen/Teddy.d.ts +10 -0
  307. package/dist/loading-screen/Teddy.d.ts.map +1 -0
  308. package/dist/loading-screen/WakeUpProgress.d.cts +16 -0
  309. package/dist/loading-screen/WakeUpProgress.d.cts.map +1 -0
  310. package/dist/loading-screen/WakeUpProgress.d.ts +16 -0
  311. package/dist/loading-screen/WakeUpProgress.d.ts.map +1 -0
  312. package/dist/loading-screen/beauty-facts.d.cts +4 -0
  313. package/dist/loading-screen/beauty-facts.d.cts.map +1 -0
  314. package/dist/loading-screen/beauty-facts.d.ts +4 -0
  315. package/dist/loading-screen/beauty-facts.d.ts.map +1 -0
  316. package/dist/loading-screen/index.cjs +405 -0
  317. package/dist/loading-screen/index.cjs.map +1 -0
  318. package/dist/loading-screen/index.d.cts +5 -0
  319. package/dist/loading-screen/index.d.cts.map +1 -0
  320. package/dist/loading-screen/index.d.ts +5 -0
  321. package/dist/loading-screen/index.d.ts.map +1 -0
  322. package/dist/loading-screen/index.js +400 -0
  323. package/dist/loading-screen/index.js.map +1 -0
  324. package/dist/loading-screen/loading-screen-icons.d.cts +6 -0
  325. package/dist/loading-screen/loading-screen-icons.d.cts.map +1 -0
  326. package/dist/loading-screen/loading-screen-icons.d.ts +6 -0
  327. package/dist/loading-screen/loading-screen-icons.d.ts.map +1 -0
  328. package/dist/media/MediaCarousel.d.cts +30 -0
  329. package/dist/media/MediaCarousel.d.cts.map +1 -0
  330. package/dist/media/MediaCarousel.d.ts +30 -0
  331. package/dist/media/MediaCarousel.d.ts.map +1 -0
  332. package/dist/media/MediaCarouselWithModal.d.cts +17 -0
  333. package/dist/media/MediaCarouselWithModal.d.cts.map +1 -0
  334. package/dist/media/MediaCarouselWithModal.d.ts +17 -0
  335. package/dist/media/MediaCarouselWithModal.d.ts.map +1 -0
  336. package/dist/media/MediaCarouselWithParentMedia.d.cts +30 -0
  337. package/dist/media/MediaCarouselWithParentMedia.d.cts.map +1 -0
  338. package/dist/media/MediaCarouselWithParentMedia.d.ts +30 -0
  339. package/dist/media/MediaCarouselWithParentMedia.d.ts.map +1 -0
  340. package/dist/media/MediaModal.d.cts +27 -0
  341. package/dist/media/MediaModal.d.cts.map +1 -0
  342. package/dist/media/MediaModal.d.ts +27 -0
  343. package/dist/media/MediaModal.d.ts.map +1 -0
  344. package/dist/media/VideoPlayer.d.cts +37 -0
  345. package/dist/media/VideoPlayer.d.cts.map +1 -0
  346. package/dist/media/VideoPlayer.d.ts +37 -0
  347. package/dist/media/VideoPlayer.d.ts.map +1 -0
  348. package/dist/media/captureVideoPoster.d.cts +20 -0
  349. package/dist/media/captureVideoPoster.d.cts.map +1 -0
  350. package/dist/media/captureVideoPoster.d.ts +20 -0
  351. package/dist/media/captureVideoPoster.d.ts.map +1 -0
  352. package/dist/media/index.cjs +613 -0
  353. package/dist/media/index.cjs.map +1 -0
  354. package/dist/media/index.d.cts +8 -0
  355. package/dist/media/index.d.cts.map +1 -0
  356. package/dist/media/index.d.ts +8 -0
  357. package/dist/media/index.d.ts.map +1 -0
  358. package/dist/media/index.js +605 -0
  359. package/dist/media/index.js.map +1 -0
  360. package/dist/media/labels.d.cts +33 -0
  361. package/dist/media/labels.d.cts.map +1 -0
  362. package/dist/media/labels.d.ts +33 -0
  363. package/dist/media/labels.d.ts.map +1 -0
  364. package/dist/media/media-icons.d.cts +6 -0
  365. package/dist/media/media-icons.d.cts.map +1 -0
  366. package/dist/media/media-icons.d.ts +6 -0
  367. package/dist/media/media-icons.d.ts.map +1 -0
  368. package/dist/media/streaming.d.cts +18 -0
  369. package/dist/media/streaming.d.cts.map +1 -0
  370. package/dist/media/streaming.d.ts +18 -0
  371. package/dist/media/streaming.d.ts.map +1 -0
  372. package/dist/resend/Resend.d.cts +37 -0
  373. package/dist/resend/Resend.d.cts.map +1 -0
  374. package/dist/resend/Resend.d.ts +37 -0
  375. package/dist/resend/Resend.d.ts.map +1 -0
  376. package/dist/resend/index.cjs +115 -0
  377. package/dist/resend/index.cjs.map +1 -0
  378. package/dist/resend/index.d.cts +2 -0
  379. package/dist/resend/index.d.cts.map +1 -0
  380. package/dist/resend/index.d.ts +2 -0
  381. package/dist/resend/index.d.ts.map +1 -0
  382. package/dist/resend/index.js +113 -0
  383. package/dist/resend/index.js.map +1 -0
  384. package/dist/static-page/StaticPage.d.cts +91 -0
  385. package/dist/static-page/StaticPage.d.cts.map +1 -0
  386. package/dist/static-page/StaticPage.d.ts +91 -0
  387. package/dist/static-page/StaticPage.d.ts.map +1 -0
  388. package/dist/static-page/index.cjs +247 -0
  389. package/dist/static-page/index.cjs.map +1 -0
  390. package/dist/static-page/index.d.cts +2 -0
  391. package/dist/static-page/index.d.cts.map +1 -0
  392. package/dist/static-page/index.d.ts +2 -0
  393. package/dist/static-page/index.d.ts.map +1 -0
  394. package/dist/static-page/index.js +235 -0
  395. package/dist/static-page/index.js.map +1 -0
  396. package/dist/static-page/static-page-icons.d.cts +6 -0
  397. package/dist/static-page/static-page-icons.d.cts.map +1 -0
  398. package/dist/static-page/static-page-icons.d.ts +6 -0
  399. package/dist/static-page/static-page-icons.d.ts.map +1 -0
  400. package/dist/stepper/Stepper.d.cts +35 -0
  401. package/dist/stepper/Stepper.d.cts.map +1 -0
  402. package/dist/stepper/Stepper.d.ts +35 -0
  403. package/dist/stepper/Stepper.d.ts.map +1 -0
  404. package/dist/stepper/index.cjs +149 -0
  405. package/dist/stepper/index.cjs.map +1 -0
  406. package/dist/stepper/index.d.cts +2 -0
  407. package/dist/stepper/index.d.cts.map +1 -0
  408. package/dist/stepper/index.d.ts +2 -0
  409. package/dist/stepper/index.d.ts.map +1 -0
  410. package/dist/stepper/index.js +147 -0
  411. package/dist/stepper/index.js.map +1 -0
  412. package/dist/stepper/stepper-icons.d.cts +10 -0
  413. package/dist/stepper/stepper-icons.d.cts.map +1 -0
  414. package/dist/stepper/stepper-icons.d.ts +10 -0
  415. package/dist/stepper/stepper-icons.d.ts.map +1 -0
  416. package/dist/testimonials/TestimonialCarousel.d.cts +40 -0
  417. package/dist/testimonials/TestimonialCarousel.d.cts.map +1 -0
  418. package/dist/testimonials/TestimonialCarousel.d.ts +40 -0
  419. package/dist/testimonials/TestimonialCarousel.d.ts.map +1 -0
  420. package/dist/testimonials/index.cjs +246 -0
  421. package/dist/testimonials/index.cjs.map +1 -0
  422. package/dist/testimonials/index.d.cts +2 -0
  423. package/dist/testimonials/index.d.cts.map +1 -0
  424. package/dist/testimonials/index.d.ts +2 -0
  425. package/dist/testimonials/index.d.ts.map +1 -0
  426. package/dist/testimonials/index.js +244 -0
  427. package/dist/testimonials/index.js.map +1 -0
  428. package/dist/testimonials/testimonials-icons.d.cts +6 -0
  429. package/dist/testimonials/testimonials-icons.d.cts.map +1 -0
  430. package/dist/testimonials/testimonials-icons.d.ts +6 -0
  431. package/dist/testimonials/testimonials-icons.d.ts.map +1 -0
  432. package/dist/theme/Theme.d.cts +23 -0
  433. package/dist/theme/Theme.d.cts.map +1 -0
  434. package/dist/theme/Theme.d.ts +23 -0
  435. package/dist/theme/Theme.d.ts.map +1 -0
  436. package/dist/theme/index.cjs +76 -0
  437. package/dist/theme/index.cjs.map +1 -0
  438. package/dist/theme/index.d.cts +2 -0
  439. package/dist/theme/index.d.cts.map +1 -0
  440. package/dist/theme/index.d.ts +2 -0
  441. package/dist/theme/index.d.ts.map +1 -0
  442. package/dist/theme/index.js +74 -0
  443. package/dist/theme/index.js.map +1 -0
  444. package/dist/theme/theme-icons.d.cts +21 -0
  445. package/dist/theme/theme-icons.d.cts.map +1 -0
  446. package/dist/theme/theme-icons.d.ts +21 -0
  447. package/dist/theme/theme-icons.d.ts.map +1 -0
  448. package/dist/toast/index.cjs +2 -38
  449. package/dist/toast/index.cjs.map +1 -1
  450. package/dist/toast/index.js +1 -37
  451. package/dist/toast/index.js.map +1 -1
  452. package/dist/ui/Badge.d.cts +12 -0
  453. package/dist/ui/Badge.d.cts.map +1 -0
  454. package/dist/ui/Badge.d.ts +12 -0
  455. package/dist/ui/Badge.d.ts.map +1 -0
  456. package/dist/ui/Divider.d.cts +12 -0
  457. package/dist/ui/Divider.d.cts.map +1 -0
  458. package/dist/ui/Divider.d.ts +12 -0
  459. package/dist/ui/Divider.d.ts.map +1 -0
  460. package/dist/ui/GradientText.d.cts +30 -0
  461. package/dist/ui/GradientText.d.cts.map +1 -0
  462. package/dist/ui/GradientText.d.ts +30 -0
  463. package/dist/ui/GradientText.d.ts.map +1 -0
  464. package/dist/ui/index.cjs +37 -3
  465. package/dist/ui/index.cjs.map +1 -1
  466. package/dist/ui/index.d.cts +3 -0
  467. package/dist/ui/index.d.cts.map +1 -1
  468. package/dist/ui/index.d.ts +3 -0
  469. package/dist/ui/index.d.ts.map +1 -1
  470. package/dist/ui/index.js +35 -4
  471. package/dist/ui/index.js.map +1 -1
  472. package/package.json +108 -6
@@ -0,0 +1,244 @@
1
+ import { addCollection, Icon } from '@iconify/react';
2
+ import { useState, useEffect, useSyncExternalStore } from 'react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var QUERY = "(prefers-reduced-motion: reduce)";
8
+ var query = /* @__PURE__ */ __name(() => window.matchMedia?.(QUERY), "query");
9
+ var subscribe = /* @__PURE__ */ __name((onChange) => {
10
+ const list = query();
11
+ list?.addEventListener("change", onChange);
12
+ return () => {
13
+ list?.removeEventListener("change", onChange);
14
+ };
15
+ }, "subscribe");
16
+ var getSnapshot = /* @__PURE__ */ __name(() => query()?.matches ?? false, "getSnapshot");
17
+ var getServerSnapshot = /* @__PURE__ */ __name(() => false, "getServerSnapshot");
18
+ var usePrefersReducedMotion = /* @__PURE__ */ __name(() => useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot), "usePrefersReducedMotion");
19
+ var createIconRegistry = /* @__PURE__ */ __name((sets) => {
20
+ let registered = false;
21
+ return {
22
+ register: /* @__PURE__ */ __name(() => {
23
+ if (registered) return;
24
+ for (const set of sets) addCollection(set);
25
+ registered = true;
26
+ }, "register"),
27
+ names: sets.flatMap(
28
+ ({ prefix, icons, aliases }) => [...Object.keys(icons), ...Object.keys(aliases ?? {})].map((name) => `${prefix}:${name}`)
29
+ )
30
+ };
31
+ }, "createIconRegistry");
32
+
33
+ // src/testimonials/testimonials-icons.ts
34
+ var ICON_SETS = [
35
+ {
36
+ prefix: "streamline-ultimate-color",
37
+ width: 24,
38
+ height: 24,
39
+ icons: {
40
+ "rating-star": {
41
+ body: '<g fill="none"><path fill="#ffef5e" d="M11.523 1.332a.511.511 0 0 1 .957 0l2.59 7.343h7.315a.512.512 0 0 1 .332.9l-6.112 5.067l2.558 7.685a.512.512 0 0 1-.788.574L12 18.224L5.622 22.9a.511.511 0 0 1-.785-.574l2.559-7.685l-6.113-5.067a.512.512 0 0 1 .332-.9h7.316z"/><path fill="#fff9bf" d="M12 18.224L5.622 22.9a.511.511 0 0 1-.785-.574l2.559-7.685l-6.113-5.067a.512.512 0 0 1 .332-.9h7.316l2.59-7.343a.51.51 0 0 1 .48-.332z"/><path stroke="#191919" stroke-linecap="round" stroke-linejoin="round" d="M11.523 1.332a.511.511 0 0 1 .957 0l2.59 7.343h7.315a.512.512 0 0 1 .332.9l-6.112 5.067l2.558 7.685a.512.512 0 0 1-.788.574L12 18.224L5.622 22.9a.511.511 0 0 1-.785-.574l2.559-7.685l-6.113-5.067a.512.512 0 0 1 .332-.9h7.316z"/></g>'
42
+ }
43
+ }
44
+ },
45
+ {
46
+ prefix: "solar",
47
+ width: 24,
48
+ height: 24,
49
+ icons: {
50
+ "arrow-left-linear": {
51
+ body: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 12H4M10 18L4 12L10 6"/>'
52
+ },
53
+ "arrow-right-linear": {
54
+ body: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M4 12H20M14 18L20 12L14 6"/>'
55
+ },
56
+ "pause-linear": {
57
+ body: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5"><path d="M2 6C2 4.11438 2 3.17157 2.58579 2.58579C3.17157 2 4.11438 2 6 2C7.88562 2 8.82843 2 9.41421 2.58579C10 3.17157 10 4.11438 10 6V18C10 19.8856 10 20.8284 9.41421 21.4142C8.82843 22 7.88562 22 6 22C4.11438 22 3.17157 22 2.58579 21.4142C2 20.8284 2 19.8856 2 18V6Z"/><path d="M14 6C14 4.11438 14 3.17157 14.5858 2.58579C15.1716 2 16.1144 2 18 2C19.8856 2 20.8284 2 21.4142 2.58579C22 3.17157 22 4.11438 22 6V18C22 19.8856 22 20.8284 21.4142 21.4142C20.8284 22 19.8856 22 18 22C16.1144 22 15.1716 22 14.5858 21.4142C14 20.8284 14 19.8856 14 18V6Z"/></g>'
58
+ },
59
+ "play-linear": {
60
+ body: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5" d="M20.4086 9.35258C22.5305 10.5065 22.5305 13.4935 20.4086 14.6474L7.59662 21.6145C5.53435 22.736 3 21.2763 3 18.9671L3 5.0329C3 2.72368 5.53435 1.26402 7.59661 2.38548L20.4086 9.35258Z"/>'
61
+ }
62
+ }
63
+ }
64
+ ];
65
+ var { register: registerTestimonialIcons, names: TESTIMONIAL_ICON_NAMES } = createIconRegistry(ICON_SETS);
66
+ var LABELS = {
67
+ carousel: "Testimonials",
68
+ previous: "Previous testimonial",
69
+ next: "Next testimonial",
70
+ pause: "Pause the testimonials",
71
+ play: "Play the testimonials",
72
+ rating: /* @__PURE__ */ __name((rating) => `Rated ${String(rating)} out of 5`, "rating"),
73
+ slide: /* @__PURE__ */ __name((index, total) => `${String(index + 1)} of ${String(total)}`, "slide")
74
+ };
75
+ var MAX_STARS = 5;
76
+ var initialsOf = /* @__PURE__ */ __name((name) => name.split(/\s+/).filter(Boolean).slice(0, 2).map((word) => Array.from(word).at(0) ?? "").join("").toUpperCase(), "initialsOf");
77
+ var IconButton = /* @__PURE__ */ __name(({
78
+ icon,
79
+ label,
80
+ onClick
81
+ }) => /* @__PURE__ */ jsx(
82
+ "button",
83
+ {
84
+ type: "button",
85
+ "aria-label": label,
86
+ onClick,
87
+ className: "text-tertiary hover:text-primary cursor-pointer rounded-sm p-0.5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-crayola-c",
88
+ children: /* @__PURE__ */ jsx(Icon, { icon, className: "size-5" })
89
+ }
90
+ ), "IconButton");
91
+ var TestimonialCarousel = /* @__PURE__ */ __name(({
92
+ testimonials,
93
+ interval = 5e3,
94
+ className = "",
95
+ labels
96
+ }) => {
97
+ registerTestimonialIcons();
98
+ const text = {
99
+ carousel: labels?.carousel ?? LABELS.carousel,
100
+ previous: labels?.previous ?? LABELS.previous,
101
+ next: labels?.next ?? LABELS.next,
102
+ pause: labels?.pause ?? LABELS.pause,
103
+ play: labels?.play ?? LABELS.play,
104
+ rating: labels?.rating ?? LABELS.rating,
105
+ slide: labels?.slide ?? LABELS.slide
106
+ };
107
+ const prefersReducedMotion = usePrefersReducedMotion();
108
+ const [index, setIndex] = useState(0);
109
+ const [isHovered, setIsHovered] = useState(false);
110
+ const [isFocused, setIsFocused] = useState(false);
111
+ const [choice, setChoice] = useState(null);
112
+ const count = testimonials.length;
113
+ const shown = Math.min(index, count - 1);
114
+ const canTurn = count > 1 && interval > 0 && !prefersReducedMotion;
115
+ const isTurning = canTurn && (choice === "playing" || choice === null && !isHovered && !isFocused);
116
+ useEffect(() => {
117
+ if (!isTurning) return;
118
+ const timer = window.setTimeout(() => {
119
+ setIndex((current) => (Math.min(current, count - 1) + 1) % count);
120
+ }, interval);
121
+ return () => {
122
+ window.clearTimeout(timer);
123
+ };
124
+ }, [isTurning, shown, count, interval]);
125
+ if (count === 0) return null;
126
+ const go = /* @__PURE__ */ __name((step) => {
127
+ setIndex((current) => (Math.min(current, count - 1) + step + count) % count);
128
+ }, "go");
129
+ return /* @__PURE__ */ jsxs(
130
+ "div",
131
+ {
132
+ role: "group",
133
+ "aria-roledescription": "carousel",
134
+ "aria-label": text.carousel,
135
+ onPointerEnter: (event) => {
136
+ if (event.pointerType === "mouse") setIsHovered(true);
137
+ },
138
+ onPointerLeave: () => {
139
+ setIsHovered(false);
140
+ },
141
+ onFocus: () => {
142
+ setIsFocused(true);
143
+ },
144
+ onBlur: (event) => {
145
+ if (!event.currentTarget.contains(event.relatedTarget)) setIsFocused(false);
146
+ },
147
+ className: `bg-tertiary-invert relative rounded-lg p-4 ${className}`,
148
+ children: [
149
+ /* @__PURE__ */ jsx("div", { "aria-live": isTurning ? "off" : "polite", children: testimonials.map((testimonial, position) => {
150
+ const stars = Math.max(
151
+ 0,
152
+ Math.min(MAX_STARS, Math.round(testimonial.rating ?? MAX_STARS))
153
+ );
154
+ return /* @__PURE__ */ jsxs(
155
+ "figure",
156
+ {
157
+ role: "group",
158
+ "aria-roledescription": "slide",
159
+ "aria-label": text.slide(position, count),
160
+ hidden: position !== shown,
161
+ className: "group m-0 flex w-full flex-col gap-4",
162
+ children: [
163
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 leading-6", children: [
164
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
165
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: text.rating(stars) }),
166
+ Array.from({ length: stars }, (_, star) => /* @__PURE__ */ jsx(
167
+ Icon,
168
+ {
169
+ "aria-hidden": "true",
170
+ icon: "streamline-ultimate-color:rating-star",
171
+ className: "size-5"
172
+ },
173
+ star
174
+ ))
175
+ ] }),
176
+ /* @__PURE__ */ jsx("blockquote", { children: /* @__PURE__ */ jsx("p", { className: "text-tertiary group-hover:text-primary text-xs break-words italic before:content-['\u201C'] after:content-['\u201D']", children: testimonial.content }) })
177
+ ] }),
178
+ /* @__PURE__ */ jsxs("figcaption", { className: "flex items-center gap-2 pr-24", children: [
179
+ testimonial.image ? /* @__PURE__ */ jsx(
180
+ "img",
181
+ {
182
+ src: testimonial.image,
183
+ alt: "",
184
+ loading: "lazy",
185
+ className: "bg-secondary-invert/50 border-primary/50 size-8 shrink-0 rounded-full border object-cover"
186
+ }
187
+ ) : /* @__PURE__ */ jsx(
188
+ "span",
189
+ {
190
+ "aria-hidden": "true",
191
+ className: "bg-secondary-invert/50 border-primary/50 text-secondary grid size-8 shrink-0 place-items-center rounded-full border text-[10px] font-semibold",
192
+ children: initialsOf(testimonial.name)
193
+ }
194
+ ),
195
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-col", children: [
196
+ /* @__PURE__ */ jsx("cite", { className: "text-secondary text-[10px] font-semibold not-italic", children: testimonial.name }),
197
+ testimonial.role && /* @__PURE__ */ jsx("span", { className: "text-tertiary text-[9px] leading-4", children: testimonial.role })
198
+ ] })
199
+ ] })
200
+ ]
201
+ },
202
+ `${testimonial.name}#${String(position)}`
203
+ );
204
+ }) }),
205
+ count > 1 && /* @__PURE__ */ jsxs("div", { className: "absolute right-4 bottom-4 flex items-center gap-1", children: [
206
+ canTurn && /* @__PURE__ */ jsx(
207
+ IconButton,
208
+ {
209
+ icon: choice === "paused" ? "solar:play-linear" : "solar:pause-linear",
210
+ label: choice === "paused" ? text.play : text.pause,
211
+ onClick: () => {
212
+ setChoice(choice === "paused" ? "playing" : "paused");
213
+ }
214
+ }
215
+ ),
216
+ /* @__PURE__ */ jsx(
217
+ IconButton,
218
+ {
219
+ icon: "solar:arrow-left-linear",
220
+ label: text.previous,
221
+ onClick: () => {
222
+ go(-1);
223
+ }
224
+ }
225
+ ),
226
+ /* @__PURE__ */ jsx(
227
+ IconButton,
228
+ {
229
+ icon: "solar:arrow-right-linear",
230
+ label: text.next,
231
+ onClick: () => {
232
+ go(1);
233
+ }
234
+ }
235
+ )
236
+ ] })
237
+ ]
238
+ }
239
+ );
240
+ }, "TestimonialCarousel");
241
+
242
+ export { TestimonialCarousel };
243
+ //# sourceMappingURL=index.js.map
244
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/usePrefersReducedMotion.ts","../../src/lib/icon-registry.ts","../../src/testimonials/testimonials-icons.ts","../../src/testimonials/TestimonialCarousel.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { useSyncExternalStore } from 'react';\n\nconst QUERY = '(prefers-reduced-motion: reduce)';\n\n// `matchMedia` is in every browser; a test environment such as jsdom may not have it, and then the\n// answer is \"no preference\" instead of an error.\nconst query = () => (window as Partial<Window>).matchMedia?.(QUERY);\n\nconst subscribe = (onChange: () => void) => {\n const list = query();\n\n list?.addEventListener('change', onChange);\n\n return () => {\n list?.removeEventListener('change', onChange);\n };\n};\n\nconst getSnapshot = () => query()?.matches ?? false;\nconst getServerSnapshot = () => false;\n\n/**\n * Whether the person asked their system for less motion. It follows the setting while the page is\n * open, and is `false` on a server (a page that moves by itself starts still there and stops once the\n * browser says so).\n */\nexport const usePrefersReducedMotion = () =>\n useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n","import { addCollection, type IconifyJSON } from '@iconify/react';\n\n/**\n * Makes the registration of a bundled icon set: `register` puts the sets in Iconify (once, calling it\n * again does nothing) and `names` lists every icon, e.g. `solar:info-circle-linear`.\n *\n * A component calls `register` when it renders, not when its file is imported: an app that never\n * renders the component never runs it, and nothing depends on the bundler keeping an import that is\n * only there for its effect (the build says \"ignored-bare-import\" for those).\n */\nexport const createIconRegistry = (sets: readonly IconifyJSON[]) => {\n let registered = false;\n\n return {\n register: () => {\n if (registered) return;\n\n for (const set of sets) addCollection(set);\n registered = true;\n },\n names: sets.flatMap(({ prefix, icons, aliases }) =>\n [...Object.keys(icons), ...Object.keys(aliases ?? {})].map((name) => `${prefix}:${name}`),\n ),\n };\n};\n","import type { IconifyJSON } from '@iconify/react';\n\nimport { createIconRegistry } from '../lib/icon-registry.js';\n\n/*\n * The icons of the testimonial carousel, bundled so they show without a network and without waiting for the\n * Iconify API (see `toast/toast-icons.ts`). The data is what\n * `https://api.iconify.design/<prefix>.json?icons=<name>` answers.\n */\nconst ICON_SETS: IconifyJSON[] = [\n {\n prefix: 'streamline-ultimate-color',\n width: 24,\n height: 24,\n icons: {\n 'rating-star': {\n body: '<g fill=\"none\"><path fill=\"#ffef5e\" d=\"M11.523 1.332a.511.511 0 0 1 .957 0l2.59 7.343h7.315a.512.512 0 0 1 .332.9l-6.112 5.067l2.558 7.685a.512.512 0 0 1-.788.574L12 18.224L5.622 22.9a.511.511 0 0 1-.785-.574l2.559-7.685l-6.113-5.067a.512.512 0 0 1 .332-.9h7.316z\"/><path fill=\"#fff9bf\" d=\"M12 18.224L5.622 22.9a.511.511 0 0 1-.785-.574l2.559-7.685l-6.113-5.067a.512.512 0 0 1 .332-.9h7.316l2.59-7.343a.51.51 0 0 1 .48-.332z\"/><path stroke=\"#191919\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M11.523 1.332a.511.511 0 0 1 .957 0l2.59 7.343h7.315a.512.512 0 0 1 .332.9l-6.112 5.067l2.558 7.685a.512.512 0 0 1-.788.574L12 18.224L5.622 22.9a.511.511 0 0 1-.785-.574l2.559-7.685l-6.113-5.067a.512.512 0 0 1 .332-.9h7.316z\"/></g>',\n },\n },\n },\n {\n prefix: 'solar',\n width: 24,\n height: 24,\n icons: {\n 'arrow-left-linear': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M20 12H4M10 18L4 12L10 6\"/>',\n },\n 'arrow-right-linear': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M4 12H20M14 18L20 12L14 6\"/>',\n },\n 'pause-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><path d=\"M2 6C2 4.11438 2 3.17157 2.58579 2.58579C3.17157 2 4.11438 2 6 2C7.88562 2 8.82843 2 9.41421 2.58579C10 3.17157 10 4.11438 10 6V18C10 19.8856 10 20.8284 9.41421 21.4142C8.82843 22 7.88562 22 6 22C4.11438 22 3.17157 22 2.58579 21.4142C2 20.8284 2 19.8856 2 18V6Z\"/><path d=\"M14 6C14 4.11438 14 3.17157 14.5858 2.58579C15.1716 2 16.1144 2 18 2C19.8856 2 20.8284 2 21.4142 2.58579C22 3.17157 22 4.11438 22 6V18C22 19.8856 22 20.8284 21.4142 21.4142C20.8284 22 19.8856 22 18 22C16.1144 22 15.1716 22 14.5858 21.4142C14 20.8284 14 19.8856 14 18V6Z\"/></g>',\n },\n 'play-linear': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\" d=\"M20.4086 9.35258C22.5305 10.5065 22.5305 13.4935 20.4086 14.6474L7.59662 21.6145C5.53435 22.736 3 21.2763 3 18.9671L3 5.0329C3 2.72368 5.53435 1.26402 7.59661 2.38548L20.4086 9.35258Z\"/>',\n },\n },\n },\n];\n\n/**\n * Registers the icons above with Iconify; the components of this entry call it when they render\n * (calling it again is harmless).\n */\nexport const { register: registerTestimonialIcons, names: TESTIMONIAL_ICON_NAMES } =\n createIconRegistry(ICON_SETS);\n","import { Icon } from '@iconify/react';\nimport { type FocusEvent, type PointerEvent, useEffect, useState } from 'react';\n\nimport { usePrefersReducedMotion } from '../lib/usePrefersReducedMotion.js';\nimport type { IClassName } from '../types/component.js';\nimport { registerTestimonialIcons } from './testimonials-icons.js';\n\nexport interface ITestimonial {\n /** What the person said. */\n content: string;\n name: string;\n role?: string;\n /** The address of a photo of the person. Without it their initials are shown. */\n image?: string;\n /** Stars, from 0 to 5. @default 5 */\n rating?: number;\n}\n\n/** The words said to assistive technology. English by default. */\nexport interface ITestimonialLabels {\n /** The name of the carousel. */\n carousel: string;\n previous: string;\n next: string;\n /** The button that stops the carousel turning by itself. */\n pause: string;\n /** The button that makes it turn by itself again. */\n play: string;\n /** What the stars say (\"Rated 5 out of 5\"). */\n rating: (rating: number) => string;\n /** The name of a slide (\"2 of 3\"). */\n slide: (index: number, total: number) => string;\n}\n\nexport interface ITestimonialCarousel extends IClassName {\n testimonials: readonly ITestimonial[];\n /** How long each testimonial stays, in milliseconds. `0` never turns by itself. @default 5000 */\n interval?: number;\n labels?: Partial<ITestimonialLabels>;\n}\n\nconst LABELS: ITestimonialLabels = {\n carousel: 'Testimonials',\n previous: 'Previous testimonial',\n next: 'Next testimonial',\n pause: 'Pause the testimonials',\n play: 'Play the testimonials',\n rating: (rating) => `Rated ${String(rating)} out of 5`,\n slide: (index, total) => `${String(index + 1)} of ${String(total)}`,\n};\n\nconst MAX_STARS = 5;\n\nconst initialsOf = (name: string) =>\n name\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((word) => Array.from(word).at(0) ?? '')\n .join('')\n .toUpperCase();\n\nconst IconButton = ({\n icon,\n label,\n onClick,\n}: {\n icon: string;\n label: string;\n onClick: () => void;\n}) => (\n <button\n type=\"button\"\n aria-label={label}\n onClick={onClick}\n className=\"text-tertiary hover:text-primary cursor-pointer rounded-sm p-0.5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-crayola-c\"\n >\n <Icon icon={icon} className=\"size-5\" />\n </button>\n);\n\n/**\n * Testimonials, one at a time, that turn by themselves. It follows what a carousel that moves has to\n * do: it stops while the pointer is over it or the focus is in it, and a button stops it (and starts\n * it again); with a system setting for less motion it does not turn at all. Previous and next buttons\n * go round, and what is announced is the slide that is current, but only while it is not turning.\n */\nexport const TestimonialCarousel = ({\n testimonials,\n interval = 5000,\n className = '',\n labels,\n}: ITestimonialCarousel) => {\n registerTestimonialIcons();\n\n const text = {\n carousel: labels?.carousel ?? LABELS.carousel,\n previous: labels?.previous ?? LABELS.previous,\n next: labels?.next ?? LABELS.next,\n pause: labels?.pause ?? LABELS.pause,\n play: labels?.play ?? LABELS.play,\n rating: labels?.rating ?? LABELS.rating,\n slide: labels?.slide ?? LABELS.slide,\n };\n const prefersReducedMotion = usePrefersReducedMotion();\n const [index, setIndex] = useState(0);\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n // what the person chose with the button; `null` while they have not\n const [choice, setChoice] = useState<'paused' | 'playing' | null>(null);\n\n const count = testimonials.length;\n const shown = Math.min(index, count - 1);\n const canTurn = count > 1 && interval > 0 && !prefersReducedMotion;\n // the button wins over the pointer and the focus: a person who pressed \"play\" wants it to turn\n const isTurning =\n canTurn && (choice === 'playing' || (choice === null && !isHovered && !isFocused));\n\n useEffect(() => {\n if (!isTurning) return;\n\n const timer = window.setTimeout(() => {\n setIndex((current) => (Math.min(current, count - 1) + 1) % count);\n }, interval);\n\n return () => {\n window.clearTimeout(timer);\n };\n }, [isTurning, shown, count, interval]);\n\n if (count === 0) return null;\n\n const go = (step: 1 | -1) => {\n setIndex((current) => (Math.min(current, count - 1) + step + count) % count);\n };\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"carousel\"\n aria-label={text.carousel}\n onPointerEnter={(event: PointerEvent<HTMLDivElement>) => {\n // a touch is not \"the pointer is over it\": there is no leaving a finger\n if (event.pointerType === 'mouse') setIsHovered(true);\n }}\n onPointerLeave={() => {\n setIsHovered(false);\n }}\n onFocus={() => {\n setIsFocused(true);\n }}\n onBlur={(event: FocusEvent<HTMLDivElement>) => {\n if (!event.currentTarget.contains(event.relatedTarget)) setIsFocused(false);\n }}\n className={`bg-tertiary-invert relative rounded-lg p-4 ${className}`}\n >\n <div aria-live={isTurning ? 'off' : 'polite'}>\n {testimonials.map((testimonial, position) => {\n const stars = Math.max(\n 0,\n Math.min(MAX_STARS, Math.round(testimonial.rating ?? MAX_STARS)),\n );\n\n return (\n <figure\n key={`${testimonial.name}#${String(position)}`}\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={text.slide(position, count)}\n hidden={position !== shown}\n className=\"group m-0 flex w-full flex-col gap-4\"\n >\n <div className=\"flex flex-col gap-4 leading-6\">\n <div className=\"flex gap-1\">\n <span className=\"sr-only\">{text.rating(stars)}</span>\n {Array.from({ length: stars }, (_, star) => (\n <Icon\n key={star}\n aria-hidden=\"true\"\n icon=\"streamline-ultimate-color:rating-star\"\n className=\"size-5\"\n />\n ))}\n </div>\n <blockquote>\n <p className=\"text-tertiary group-hover:text-primary text-xs break-words italic before:content-['“'] after:content-['”']\">\n {testimonial.content}\n </p>\n </blockquote>\n </div>\n <figcaption className=\"flex items-center gap-2 pr-24\">\n {testimonial.image ? (\n <img\n src={testimonial.image}\n alt=\"\"\n loading=\"lazy\"\n className=\"bg-secondary-invert/50 border-primary/50 size-8 shrink-0 rounded-full border object-cover\"\n />\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"bg-secondary-invert/50 border-primary/50 text-secondary grid size-8 shrink-0 place-items-center rounded-full border text-[10px] font-semibold\"\n >\n {initialsOf(testimonial.name)}\n </span>\n )}\n <span className=\"flex flex-col\">\n <cite className=\"text-secondary text-[10px] font-semibold not-italic\">\n {testimonial.name}\n </cite>\n {testimonial.role && (\n <span className=\"text-tertiary text-[9px] leading-4\">{testimonial.role}</span>\n )}\n </span>\n </figcaption>\n </figure>\n );\n })}\n </div>\n\n {count > 1 && (\n <div className=\"absolute right-4 bottom-4 flex items-center gap-1\">\n {canTurn && (\n <IconButton\n icon={choice === 'paused' ? 'solar:play-linear' : 'solar:pause-linear'}\n label={choice === 'paused' ? text.play : text.pause}\n onClick={() => {\n setChoice(choice === 'paused' ? 'playing' : 'paused');\n }}\n />\n )}\n <IconButton\n icon=\"solar:arrow-left-linear\"\n label={text.previous}\n onClick={() => {\n go(-1);\n }}\n />\n <IconButton\n icon=\"solar:arrow-right-linear\"\n label={text.next}\n onClick={() => {\n go(1);\n }}\n />\n </div>\n )}\n </div>\n );\n};\n"]}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Registers the icons above with Iconify; the components of this entry call it when they render
3
+ * (calling it again is harmless).
4
+ */
5
+ export declare const registerTestimonialIcons: () => void, TESTIMONIAL_ICON_NAMES: string[];
6
+ //# sourceMappingURL=testimonials-icons.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testimonials-icons.d.cts","sourceRoot":"","sources":["../../src/testimonials/testimonials-icons.ts"],"names":[],"mappings":"AAyCA;;;GAGG;AACH,eAAO,MAAkB,wBAAwB,cAAS,sBAAsB,UACjD,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Registers the icons above with Iconify; the components of this entry call it when they render
3
+ * (calling it again is harmless).
4
+ */
5
+ export declare const registerTestimonialIcons: () => void, TESTIMONIAL_ICON_NAMES: string[];
6
+ //# sourceMappingURL=testimonials-icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testimonials-icons.d.ts","sourceRoot":"","sources":["../../src/testimonials/testimonials-icons.ts"],"names":[],"mappings":"AAyCA;;;GAGG;AACH,eAAO,MAAkB,wBAAwB,cAAS,sBAAsB,UACjD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { TThemeStoreHook } from '@beautinique/frontend-stores';
2
+ import type { ComponentProps } from 'react';
3
+ export interface ITheme extends Omit<ComponentProps<'button'>, 'children' | 'onClick' | 'type' | 'aria-label'> {
4
+ /** The theme store of the app: what `createThemeStore()` of `@beautinique/frontend-stores` gave it. */
5
+ store: TThemeStoreHook;
6
+ /** What the button says to assistive technology, for the theme it would switch to. */
7
+ labels?: {
8
+ /** @default 'Switch to light theme' */
9
+ toLight?: string;
10
+ /** @default 'Switch to dark theme' */
11
+ toDark?: string;
12
+ };
13
+ }
14
+ /**
15
+ * A button that switches between the dark and the light theme. It shows the theme it would switch
16
+ * to: a sun while the theme is dark, a moon while it is light. It only changes the store; putting the
17
+ * theme on the page (a class on `<html>`) is the app's.
18
+ *
19
+ * The icons move; for a person who asked their system for less motion (`prefers-reduced-motion`)
20
+ * the button shows still ones instead.
21
+ */
22
+ export declare const Theme: ({ store: useThemeStore, labels, className, ...buttonProps }: ITheme) => import("react").JSX.Element;
23
+ //# sourceMappingURL=Theme.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Theme.d.cts","sourceRoot":"","sources":["../../src/theme/Theme.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAI5C,MAAM,WAAW,MAAO,SAAQ,IAAI,CAClC,cAAc,CAAC,QAAQ,CAAC,EACxB,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,CAC/C;IACC,uGAAuG;IACvG,KAAK,EAAE,eAAe,CAAC;IACvB,sFAAsF;IACtF,MAAM,CAAC,EAAE;QACP,uCAAuC;QACvC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,sCAAsC;QACtC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAWD;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,GAAI,6DAAkE,MAAM,gCAuB7F,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { TThemeStoreHook } from '@beautinique/frontend-stores';
2
+ import type { ComponentProps } from 'react';
3
+ export interface ITheme extends Omit<ComponentProps<'button'>, 'children' | 'onClick' | 'type' | 'aria-label'> {
4
+ /** The theme store of the app: what `createThemeStore()` of `@beautinique/frontend-stores` gave it. */
5
+ store: TThemeStoreHook;
6
+ /** What the button says to assistive technology, for the theme it would switch to. */
7
+ labels?: {
8
+ /** @default 'Switch to light theme' */
9
+ toLight?: string;
10
+ /** @default 'Switch to dark theme' */
11
+ toDark?: string;
12
+ };
13
+ }
14
+ /**
15
+ * A button that switches between the dark and the light theme. It shows the theme it would switch
16
+ * to: a sun while the theme is dark, a moon while it is light. It only changes the store; putting the
17
+ * theme on the page (a class on `<html>`) is the app's.
18
+ *
19
+ * The icons move; for a person who asked their system for less motion (`prefers-reduced-motion`)
20
+ * the button shows still ones instead.
21
+ */
22
+ export declare const Theme: ({ store: useThemeStore, labels, className, ...buttonProps }: ITheme) => import("react").JSX.Element;
23
+ //# sourceMappingURL=Theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Theme.d.ts","sourceRoot":"","sources":["../../src/theme/Theme.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAI5C,MAAM,WAAW,MAAO,SAAQ,IAAI,CAClC,cAAc,CAAC,QAAQ,CAAC,EACxB,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,CAC/C;IACC,uGAAuG;IACvG,KAAK,EAAE,eAAe,CAAC;IACvB,sFAAsF;IACtF,MAAM,CAAC,EAAE;QACP,uCAAuC;QACvC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,sCAAsC;QACtC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAWD;;;;;;;GAOG;AACH,eAAO,MAAM,KAAK,GAAI,6DAAkE,MAAM,gCAuB7F,CAAC"}
@@ -0,0 +1,76 @@
1
+ 'use strict';
2
+
3
+ var react = require('@iconify/react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ var __defProp = Object.defineProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var THEME_ICON_SETS = [
9
+ {
10
+ prefix: "line-md",
11
+ width: 24,
12
+ height: 24,
13
+ icons: {
14
+ "sunny-loop": {
15
+ body: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path stroke-dasharray="34" d="M12 7c2.76 0 5 2.24 5 5c0 2.76 -2.24 5 -5 5c-2.76 0 -5 -2.24 -5 -5c0 -2.76 2.24 -5 5 -5Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.4s" values="34;0"/></path><path d="M12 21v1M21 12h1M12 3v-1M3 12h-1" opacity="0"><animateTransform attributeName="transform" dur="30s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/><set fill="freeze" attributeName="opacity" begin="0.5s" to="1"/><animate fill="freeze" attributeName="d" begin="0.5s" dur="0.2s" values="M12 19v1M19 12h1M12 5v-1M5 12h-1;M12 21v1M21 12h1M12 3v-1M3 12h-1"/></path><path d="M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5" opacity="0"><animateTransform attributeName="transform" dur="30s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/><set fill="freeze" attributeName="opacity" begin="0.7s" to="1"/><animate fill="freeze" attributeName="d" begin="0.7s" dur="0.2s" values="M17 17l0.5 0.5M17 7l0.5 -0.5M7 7l-0.5 -0.5M7 17l-0.5 0.5;M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5"/></path></g>'
16
+ },
17
+ "moon-loop": {
18
+ body: '<path fill="none" stroke="currentColor" stroke-dasharray="56" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 6c0 6.08 4.92 11 11 11c0.53 0 1.05 -0.04 1.56 -0.11c-1.61 2.47 -4.39 4.11 -7.56 4.11c-4.97 0 -9 -4.03 -9 -9c0 -3.17 1.64 -5.95 4.11 -7.56c-0.07 0.51 -0.11 1.03 -0.11 1.56Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.6s" values="56;0"/></path><g fill="currentColor"><path d="M15.22 6.03l2.53 -1.94l-3.19 -0.09l-1.06 -3l-1.06 3l-3.19 0.09l2.53 1.94l-0.91 3.06l2.63 -1.81l2.63 1.81l-0.91 -3.06Z" opacity="0"><animate attributeName="opacity" begin="0.7s" dur="6s" keyTimes="0;0.1;0.4;0.5;1" repeatCount="indefinite" values="0;1;1;0;0"/></path><path d="M19.61 12.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17l-0.59 -1.98Z" opacity="0"><animate attributeName="opacity" begin="0.7s" dur="6s" keyTimes="0;0.2;0.3;0.6;0.7;1" repeatCount="indefinite" values="0;0;1;1;0;0"/></path><path d="M13.61 5.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17Z" opacity="0"><animate attributeName="opacity" begin="3.7s" dur="6s" keyTimes="0;0.1;0.4;0.5;1" repeatCount="indefinite" values="0;1;1;0;0"/></path><path d="M20.83 9.73l1.88 -1.44l-2.37 -0.07l-0.79 -2.22l-0.79 2.23l-2.37 0.07l1.88 1.44l-0.68 2.27l1.95 -1.34l1.95 1.34Z" opacity="0"><animate attributeName="opacity" begin="3.7s" dur="6s" keyTimes="0;0.2;0.3;0.6;0.7;1" repeatCount="indefinite" values="0;0;1;1;0;0"/></path></g>'
19
+ }
20
+ }
21
+ },
22
+ {
23
+ prefix: "solar",
24
+ width: 24,
25
+ height: 24,
26
+ icons: {
27
+ "sun-2-linear": {
28
+ body: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5"><circle cx="12" cy="12" r="5"/><path d="M12 2V4"/><path d="M12 20V22"/><path d="M4 12L2 12"/><path d="M22 12L20 12"/><path d="M19.7778 4.22266L17.5558 6.25424"/><path d="M4.22217 4.22266L6.44418 6.25424"/><path d="M6.44434 17.5557L4.22211 19.7779"/><path d="M19.7778 19.7773L17.5558 17.5551"/></g>'
29
+ },
30
+ "moon-linear": {
31
+ body: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 22C17.5228 22 22 17.5228 22 12C22 11.5373 21.3065 11.4608 21.0672 11.8568C19.9289 13.7406 17.8615 15 15.5 15C11.9101 15 9 12.0899 9 8.5C9 6.13845 10.2594 4.07105 12.1432 2.93276C12.5392 2.69347 12.4627 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"/>'
32
+ }
33
+ }
34
+ }
35
+ ];
36
+ var THEME_ICONS = {
37
+ dark: { moving: "line-md:sunny-loop", still: "solar:sun-2-linear" },
38
+ light: { moving: "line-md:moon-loop", still: "solar:moon-linear" }
39
+ };
40
+ var registered = false;
41
+ var registerThemeIcons = /* @__PURE__ */ __name(() => {
42
+ if (registered) return;
43
+ for (const iconSet of THEME_ICON_SETS) react.addCollection(iconSet);
44
+ registered = true;
45
+ }, "registerThemeIcons");
46
+ THEME_ICON_SETS.flatMap(
47
+ ({ prefix, icons }) => Object.keys(icons).map((name) => `${prefix}:${name}`)
48
+ );
49
+ var BUTTON_CSS = "relative size-5 cursor-pointer rounded-full after:absolute after:-inset-1 after:content-[''] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-crayola-c md:size-6";
50
+ var ICON_CSS = "text-tertiary hover:text-secondary size-full [&_path]:stroke-[1.5]";
51
+ var Theme = /* @__PURE__ */ __name(({ store: useThemeStore, labels, className = "", ...buttonProps }) => {
52
+ registerThemeIcons();
53
+ const theme = useThemeStore((state) => state.theme);
54
+ const toggleTheme = useThemeStore((state) => state.toggleTheme);
55
+ const isDark = theme === "dark";
56
+ const icons = THEME_ICONS[isDark ? "dark" : "light"];
57
+ const { toLight = "Switch to light theme", toDark = "Switch to dark theme" } = labels ?? {};
58
+ return /* @__PURE__ */ jsxRuntime.jsxs(
59
+ "button",
60
+ {
61
+ ...buttonProps,
62
+ type: "button",
63
+ onClick: toggleTheme,
64
+ "aria-label": isDark ? toLight : toDark,
65
+ className: `${BUTTON_CSS} ${className}`,
66
+ children: [
67
+ /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: icons.moving, className: `${ICON_CSS} motion-reduce:hidden` }),
68
+ /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: icons.still, className: `${ICON_CSS} hidden motion-reduce:block` })
69
+ ]
70
+ }
71
+ );
72
+ }, "Theme");
73
+
74
+ exports.Theme = Theme;
75
+ //# sourceMappingURL=index.cjs.map
76
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/theme/theme-icons.ts","../../src/theme/Theme.tsx"],"names":["addCollection","jsxs","jsx","Icon"],"mappings":";;;;;;;AAYA,IAAM,eAAA,GAAiC;AAAA,EACrC;AAAA,IACE,MAAA,EAAQ,SAAA;AAAA,IACR,KAAA,EAAO,EAAA;AAAA,IACP,MAAA,EAAQ,EAAA;AAAA,IACR,KAAA,EAAO;AAAA,MACL,YAAA,EAAc;AAAA,QACZ,IAAA,EAAM;AAAA,OACR;AAAA,MACA,WAAA,EAAa;AAAA,QACX,IAAA,EAAM;AAAA;AACR;AACF,GACF;AAAA,EACA;AAAA,IACE,MAAA,EAAQ,OAAA;AAAA,IACR,KAAA,EAAO,EAAA;AAAA,IACP,MAAA,EAAQ,EAAA;AAAA,IACR,KAAA,EAAO;AAAA,MACL,cAAA,EAAgB;AAAA,QACd,IAAA,EAAM;AAAA,OACR;AAAA,MACA,aAAA,EAAe;AAAA,QACb,IAAA,EAAM;AAAA;AACR;AACF;AAEJ,CAAA;AAGO,IAAM,WAAA,GAAc;AAAA,EACzB,IAAA,EAAM,EAAE,MAAA,EAAQ,oBAAA,EAAsB,OAAO,oBAAA,EAAqB;AAAA,EAClE,KAAA,EAAO,EAAE,MAAA,EAAQ,mBAAA,EAAqB,OAAO,mBAAA;AAC/C,CAAA;AAEA,IAAI,UAAA,GAAa,KAAA;AAQV,IAAM,qCAAqB,MAAA,CAAA,MAAM;AACtC,EAAA,IAAI,UAAA,EAAY;AAEhB,EAAA,KAAA,MAAW,OAAA,IAAW,eAAA,EAAiBA,mBAAA,CAAc,OAAO,CAAA;AAC5D,EAAA,UAAA,GAAa,IAAA;AACf,CAAA,EALkC,oBAAA,CAAA;AAQF,eAAA,CAAgB,OAAA;AAAA,EAAQ,CAAC,EAAE,MAAA,EAAQ,KAAA,EAAM,KACvE,OAAO,IAAA,CAAK,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE;AACtD;ACvCA,IAAM,UAAA,GACJ,oMAAA;AACF,IAAM,QAAA,GAAW,oEAAA;AAUV,IAAM,KAAA,mBAAQ,MAAA,CAAA,CAAC,EAAE,KAAA,EAAO,aAAA,EAAe,QAAQ,SAAA,GAAY,EAAA,EAAI,GAAG,WAAA,EAAY,KAAc;AACjG,EAAA,kBAAA,EAAmB;AAEnB,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,CAAC,KAAA,KAAU,MAAM,KAAK,CAAA;AAClD,EAAA,MAAM,WAAA,GAAc,aAAA,CAAc,CAAC,KAAA,KAAU,MAAM,WAAW,CAAA;AAE9D,EAAA,MAAM,SAAS,KAAA,KAAU,MAAA;AACzB,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,MAAA,GAAS,MAAA,GAAS,OAAO,CAAA;AACnD,EAAA,MAAM,EAAE,OAAA,GAAU,uBAAA,EAAyB,SAAS,sBAAA,EAAuB,GAAI,UAAU,EAAC;AAE1F,EAAA,uBACEC,eAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACE,GAAG,WAAA;AAAA,MACJ,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,WAAA;AAAA,MACT,YAAA,EAAY,SAAS,OAAA,GAAU,MAAA;AAAA,MAC/B,SAAA,EAAW,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,MAGrC,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAACC,cAAK,IAAA,EAAM,KAAA,CAAM,QAAQ,SAAA,EAAW,CAAA,EAAG,QAAQ,CAAA,qBAAA,CAAA,EAAyB,CAAA;AAAA,wBACzED,cAAA,CAACC,cAAK,IAAA,EAAM,KAAA,CAAM,OAAO,SAAA,EAAW,CAAA,EAAG,QAAQ,CAAA,2BAAA,CAAA,EAA+B;AAAA;AAAA;AAAA,GAChF;AAEJ,CAAA,EAvBqB,OAAA","file":"index.cjs","sourcesContent":["import { addCollection, type IconifyJSON } from '@iconify/react';\n\n/*\n * The icons of the theme button. Iconify downloads an icon from its API the first time it is shown,\n * which cannot work offline and leaves the button empty until it arrives, so they are bundled here and\n * registered with Iconify (the same way as the toast icons, see `toast-icons.ts`).\n *\n * For each theme there are two: one that moves (`line-md`, drawn with SMIL and never stops) and a\n * still one (`solar`) for a person who asked for less motion.\n *\n * The data is what `https://api.iconify.design/<prefix>.json?icons=<name>` answers.\n */\nconst THEME_ICON_SETS: IconifyJSON[] = [\n {\n prefix: 'line-md',\n width: 24,\n height: 24,\n icons: {\n 'sunny-loop': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path stroke-dasharray=\"34\" d=\"M12 7c2.76 0 5 2.24 5 5c0 2.76 -2.24 5 -5 5c-2.76 0 -5 -2.24 -5 -5c0 -2.76 2.24 -5 5 -5Z\"><animate fill=\"freeze\" attributeName=\"stroke-dashoffset\" dur=\"0.4s\" values=\"34;0\"/></path><path d=\"M12 21v1M21 12h1M12 3v-1M3 12h-1\" opacity=\"0\"><animateTransform attributeName=\"transform\" dur=\"30s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\"/><set fill=\"freeze\" attributeName=\"opacity\" begin=\"0.5s\" to=\"1\"/><animate fill=\"freeze\" attributeName=\"d\" begin=\"0.5s\" dur=\"0.2s\" values=\"M12 19v1M19 12h1M12 5v-1M5 12h-1;M12 21v1M21 12h1M12 3v-1M3 12h-1\"/></path><path d=\"M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5\" opacity=\"0\"><animateTransform attributeName=\"transform\" dur=\"30s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\"/><set fill=\"freeze\" attributeName=\"opacity\" begin=\"0.7s\" to=\"1\"/><animate fill=\"freeze\" attributeName=\"d\" begin=\"0.7s\" dur=\"0.2s\" values=\"M17 17l0.5 0.5M17 7l0.5 -0.5M7 7l-0.5 -0.5M7 17l-0.5 0.5;M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5\"/></path></g>',\n },\n 'moon-loop': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-dasharray=\"56\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 6c0 6.08 4.92 11 11 11c0.53 0 1.05 -0.04 1.56 -0.11c-1.61 2.47 -4.39 4.11 -7.56 4.11c-4.97 0 -9 -4.03 -9 -9c0 -3.17 1.64 -5.95 4.11 -7.56c-0.07 0.51 -0.11 1.03 -0.11 1.56Z\"><animate fill=\"freeze\" attributeName=\"stroke-dashoffset\" dur=\"0.6s\" values=\"56;0\"/></path><g fill=\"currentColor\"><path d=\"M15.22 6.03l2.53 -1.94l-3.19 -0.09l-1.06 -3l-1.06 3l-3.19 0.09l2.53 1.94l-0.91 3.06l2.63 -1.81l2.63 1.81l-0.91 -3.06Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"0.7s\" dur=\"6s\" keyTimes=\"0;0.1;0.4;0.5;1\" repeatCount=\"indefinite\" values=\"0;1;1;0;0\"/></path><path d=\"M19.61 12.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17l-0.59 -1.98Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"0.7s\" dur=\"6s\" keyTimes=\"0;0.2;0.3;0.6;0.7;1\" repeatCount=\"indefinite\" values=\"0;0;1;1;0;0\"/></path><path d=\"M13.61 5.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"3.7s\" dur=\"6s\" keyTimes=\"0;0.1;0.4;0.5;1\" repeatCount=\"indefinite\" values=\"0;1;1;0;0\"/></path><path d=\"M20.83 9.73l1.88 -1.44l-2.37 -0.07l-0.79 -2.22l-0.79 2.23l-2.37 0.07l1.88 1.44l-0.68 2.27l1.95 -1.34l1.95 1.34Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"3.7s\" dur=\"6s\" keyTimes=\"0;0.2;0.3;0.6;0.7;1\" repeatCount=\"indefinite\" values=\"0;0;1;1;0;0\"/></path></g>',\n },\n },\n },\n {\n prefix: 'solar',\n width: 24,\n height: 24,\n icons: {\n 'sun-2-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"5\"/><path d=\"M12 2V4\"/><path d=\"M12 20V22\"/><path d=\"M4 12L2 12\"/><path d=\"M22 12L20 12\"/><path d=\"M19.7778 4.22266L17.5558 6.25424\"/><path d=\"M4.22217 4.22266L6.44418 6.25424\"/><path d=\"M6.44434 17.5557L4.22211 19.7779\"/><path d=\"M19.7778 19.7773L17.5558 17.5551\"/></g>',\n },\n 'moon-linear': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M12 22C17.5228 22 22 17.5228 22 12C22 11.5373 21.3065 11.4608 21.0672 11.8568C19.9289 13.7406 17.8615 15 15.5 15C11.9101 15 9 12.0899 9 8.5C9 6.13845 10.2594 4.07105 12.1432 2.93276C12.5392 2.69347 12.4627 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z\"/>',\n },\n },\n },\n];\n\n/** What the button shows while the theme is dark (a sun: it would switch to light) and light (a moon). */\nexport const THEME_ICONS = {\n dark: { moving: 'line-md:sunny-loop', still: 'solar:sun-2-linear' },\n light: { moving: 'line-md:moon-loop', still: 'solar:moon-linear' },\n} as const;\n\nlet registered = false;\n\n/**\n * Registers the icons above with Iconify. `Theme` calls it when it renders, not when this file is\n * imported: an app that never renders the button never runs it, and nothing depends on the bundler\n * keeping an import that is only there for its effect (see `toast-icons.ts`). Calling it again is\n * harmless.\n */\nexport const registerThemeIcons = () => {\n if (registered) return;\n\n for (const iconSet of THEME_ICON_SETS) addCollection(iconSet);\n registered = true;\n};\n\n/** Every icon name registered above, e.g. `line-md:sunny-loop`. */\nexport const THEME_ICON_NAMES = THEME_ICON_SETS.flatMap(({ prefix, icons }) =>\n Object.keys(icons).map((name) => `${prefix}:${name}`),\n);\n","import type { TThemeStoreHook } from '@beautinique/frontend-stores';\nimport { Icon } from '@iconify/react';\nimport type { ComponentProps } from 'react';\n\nimport { registerThemeIcons, THEME_ICONS } from './theme-icons.js';\n\nexport interface ITheme extends Omit<\n ComponentProps<'button'>,\n 'children' | 'onClick' | 'type' | 'aria-label'\n> {\n /** The theme store of the app: what `createThemeStore()` of `@beautinique/frontend-stores` gave it. */\n store: TThemeStoreHook;\n /** What the button says to assistive technology, for the theme it would switch to. */\n labels?: {\n /** @default 'Switch to light theme' */\n toLight?: string;\n /** @default 'Switch to dark theme' */\n toDark?: string;\n };\n}\n\n// The hit area is bigger than the icon (the icon is 20px on a phone): the `after` box is a part of the\n// button, so a thumb that lands next to the icon still presses it, and nothing around it moves.\n// No `outline-hidden`: in Tailwind v4 it sets `--tw-outline-style: none`, which the\n// `focus-visible:outline-2` uses for its style, so the ring would never be drawn. A button only shows\n// the browser's own ring for the keyboard anyway (`:focus-visible`), never for a click.\nconst BUTTON_CSS =\n \"relative size-5 cursor-pointer rounded-full after:absolute after:-inset-1 after:content-[''] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-crayola-c md:size-6\";\nconst ICON_CSS = 'text-tertiary hover:text-secondary size-full [&_path]:stroke-[1.5]';\n\n/**\n * A button that switches between the dark and the light theme. It shows the theme it would switch\n * to: a sun while the theme is dark, a moon while it is light. It only changes the store; putting the\n * theme on the page (a class on `<html>`) is the app's.\n *\n * The icons move; for a person who asked their system for less motion (`prefers-reduced-motion`)\n * the button shows still ones instead.\n */\nexport const Theme = ({ store: useThemeStore, labels, className = '', ...buttonProps }: ITheme) => {\n registerThemeIcons();\n\n const theme = useThemeStore((state) => state.theme);\n const toggleTheme = useThemeStore((state) => state.toggleTheme);\n\n const isDark = theme === 'dark';\n const icons = THEME_ICONS[isDark ? 'dark' : 'light'];\n const { toLight = 'Switch to light theme', toDark = 'Switch to dark theme' } = labels ?? {};\n\n return (\n <button\n {...buttonProps}\n type=\"button\"\n onClick={toggleTheme}\n aria-label={isDark ? toLight : toDark}\n className={`${BUTTON_CSS} ${className}`}\n >\n {/* Both are in the page and css picks one: no script has to ask the system about motion. */}\n <Icon icon={icons.moving} className={`${ICON_CSS} motion-reduce:hidden`} />\n <Icon icon={icons.still} className={`${ICON_CSS} hidden motion-reduce:block`} />\n </button>\n );\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export { type ITheme, Theme } from './Theme.js';
2
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { type ITheme, Theme } from './Theme.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { Icon, addCollection } from '@iconify/react';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
+ var THEME_ICON_SETS = [
7
+ {
8
+ prefix: "line-md",
9
+ width: 24,
10
+ height: 24,
11
+ icons: {
12
+ "sunny-loop": {
13
+ body: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path stroke-dasharray="34" d="M12 7c2.76 0 5 2.24 5 5c0 2.76 -2.24 5 -5 5c-2.76 0 -5 -2.24 -5 -5c0 -2.76 2.24 -5 5 -5Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.4s" values="34;0"/></path><path d="M12 21v1M21 12h1M12 3v-1M3 12h-1" opacity="0"><animateTransform attributeName="transform" dur="30s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/><set fill="freeze" attributeName="opacity" begin="0.5s" to="1"/><animate fill="freeze" attributeName="d" begin="0.5s" dur="0.2s" values="M12 19v1M19 12h1M12 5v-1M5 12h-1;M12 21v1M21 12h1M12 3v-1M3 12h-1"/></path><path d="M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5" opacity="0"><animateTransform attributeName="transform" dur="30s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/><set fill="freeze" attributeName="opacity" begin="0.7s" to="1"/><animate fill="freeze" attributeName="d" begin="0.7s" dur="0.2s" values="M17 17l0.5 0.5M17 7l0.5 -0.5M7 7l-0.5 -0.5M7 17l-0.5 0.5;M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5"/></path></g>'
14
+ },
15
+ "moon-loop": {
16
+ body: '<path fill="none" stroke="currentColor" stroke-dasharray="56" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 6c0 6.08 4.92 11 11 11c0.53 0 1.05 -0.04 1.56 -0.11c-1.61 2.47 -4.39 4.11 -7.56 4.11c-4.97 0 -9 -4.03 -9 -9c0 -3.17 1.64 -5.95 4.11 -7.56c-0.07 0.51 -0.11 1.03 -0.11 1.56Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.6s" values="56;0"/></path><g fill="currentColor"><path d="M15.22 6.03l2.53 -1.94l-3.19 -0.09l-1.06 -3l-1.06 3l-3.19 0.09l2.53 1.94l-0.91 3.06l2.63 -1.81l2.63 1.81l-0.91 -3.06Z" opacity="0"><animate attributeName="opacity" begin="0.7s" dur="6s" keyTimes="0;0.1;0.4;0.5;1" repeatCount="indefinite" values="0;1;1;0;0"/></path><path d="M19.61 12.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17l-0.59 -1.98Z" opacity="0"><animate attributeName="opacity" begin="0.7s" dur="6s" keyTimes="0;0.2;0.3;0.6;0.7;1" repeatCount="indefinite" values="0;0;1;1;0;0"/></path><path d="M13.61 5.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17Z" opacity="0"><animate attributeName="opacity" begin="3.7s" dur="6s" keyTimes="0;0.1;0.4;0.5;1" repeatCount="indefinite" values="0;1;1;0;0"/></path><path d="M20.83 9.73l1.88 -1.44l-2.37 -0.07l-0.79 -2.22l-0.79 2.23l-2.37 0.07l1.88 1.44l-0.68 2.27l1.95 -1.34l1.95 1.34Z" opacity="0"><animate attributeName="opacity" begin="3.7s" dur="6s" keyTimes="0;0.2;0.3;0.6;0.7;1" repeatCount="indefinite" values="0;0;1;1;0;0"/></path></g>'
17
+ }
18
+ }
19
+ },
20
+ {
21
+ prefix: "solar",
22
+ width: 24,
23
+ height: 24,
24
+ icons: {
25
+ "sun-2-linear": {
26
+ body: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.5"><circle cx="12" cy="12" r="5"/><path d="M12 2V4"/><path d="M12 20V22"/><path d="M4 12L2 12"/><path d="M22 12L20 12"/><path d="M19.7778 4.22266L17.5558 6.25424"/><path d="M4.22217 4.22266L6.44418 6.25424"/><path d="M6.44434 17.5557L4.22211 19.7779"/><path d="M19.7778 19.7773L17.5558 17.5551"/></g>'
27
+ },
28
+ "moon-linear": {
29
+ body: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 22C17.5228 22 22 17.5228 22 12C22 11.5373 21.3065 11.4608 21.0672 11.8568C19.9289 13.7406 17.8615 15 15.5 15C11.9101 15 9 12.0899 9 8.5C9 6.13845 10.2594 4.07105 12.1432 2.93276C12.5392 2.69347 12.4627 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"/>'
30
+ }
31
+ }
32
+ }
33
+ ];
34
+ var THEME_ICONS = {
35
+ dark: { moving: "line-md:sunny-loop", still: "solar:sun-2-linear" },
36
+ light: { moving: "line-md:moon-loop", still: "solar:moon-linear" }
37
+ };
38
+ var registered = false;
39
+ var registerThemeIcons = /* @__PURE__ */ __name(() => {
40
+ if (registered) return;
41
+ for (const iconSet of THEME_ICON_SETS) addCollection(iconSet);
42
+ registered = true;
43
+ }, "registerThemeIcons");
44
+ THEME_ICON_SETS.flatMap(
45
+ ({ prefix, icons }) => Object.keys(icons).map((name) => `${prefix}:${name}`)
46
+ );
47
+ var BUTTON_CSS = "relative size-5 cursor-pointer rounded-full after:absolute after:-inset-1 after:content-[''] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-crayola-c md:size-6";
48
+ var ICON_CSS = "text-tertiary hover:text-secondary size-full [&_path]:stroke-[1.5]";
49
+ var Theme = /* @__PURE__ */ __name(({ store: useThemeStore, labels, className = "", ...buttonProps }) => {
50
+ registerThemeIcons();
51
+ const theme = useThemeStore((state) => state.theme);
52
+ const toggleTheme = useThemeStore((state) => state.toggleTheme);
53
+ const isDark = theme === "dark";
54
+ const icons = THEME_ICONS[isDark ? "dark" : "light"];
55
+ const { toLight = "Switch to light theme", toDark = "Switch to dark theme" } = labels ?? {};
56
+ return /* @__PURE__ */ jsxs(
57
+ "button",
58
+ {
59
+ ...buttonProps,
60
+ type: "button",
61
+ onClick: toggleTheme,
62
+ "aria-label": isDark ? toLight : toDark,
63
+ className: `${BUTTON_CSS} ${className}`,
64
+ children: [
65
+ /* @__PURE__ */ jsx(Icon, { icon: icons.moving, className: `${ICON_CSS} motion-reduce:hidden` }),
66
+ /* @__PURE__ */ jsx(Icon, { icon: icons.still, className: `${ICON_CSS} hidden motion-reduce:block` })
67
+ ]
68
+ }
69
+ );
70
+ }, "Theme");
71
+
72
+ export { Theme };
73
+ //# sourceMappingURL=index.js.map
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/theme/theme-icons.ts","../../src/theme/Theme.tsx"],"names":[],"mappings":";;;;;AAYA,IAAM,eAAA,GAAiC;AAAA,EACrC;AAAA,IACE,MAAA,EAAQ,SAAA;AAAA,IACR,KAAA,EAAO,EAAA;AAAA,IACP,MAAA,EAAQ,EAAA;AAAA,IACR,KAAA,EAAO;AAAA,MACL,YAAA,EAAc;AAAA,QACZ,IAAA,EAAM;AAAA,OACR;AAAA,MACA,WAAA,EAAa;AAAA,QACX,IAAA,EAAM;AAAA;AACR;AACF,GACF;AAAA,EACA;AAAA,IACE,MAAA,EAAQ,OAAA;AAAA,IACR,KAAA,EAAO,EAAA;AAAA,IACP,MAAA,EAAQ,EAAA;AAAA,IACR,KAAA,EAAO;AAAA,MACL,cAAA,EAAgB;AAAA,QACd,IAAA,EAAM;AAAA,OACR;AAAA,MACA,aAAA,EAAe;AAAA,QACb,IAAA,EAAM;AAAA;AACR;AACF;AAEJ,CAAA;AAGO,IAAM,WAAA,GAAc;AAAA,EACzB,IAAA,EAAM,EAAE,MAAA,EAAQ,oBAAA,EAAsB,OAAO,oBAAA,EAAqB;AAAA,EAClE,KAAA,EAAO,EAAE,MAAA,EAAQ,mBAAA,EAAqB,OAAO,mBAAA;AAC/C,CAAA;AAEA,IAAI,UAAA,GAAa,KAAA;AAQV,IAAM,qCAAqB,MAAA,CAAA,MAAM;AACtC,EAAA,IAAI,UAAA,EAAY;AAEhB,EAAA,KAAA,MAAW,OAAA,IAAW,eAAA,EAAiB,aAAA,CAAc,OAAO,CAAA;AAC5D,EAAA,UAAA,GAAa,IAAA;AACf,CAAA,EALkC,oBAAA,CAAA;AAQF,eAAA,CAAgB,OAAA;AAAA,EAAQ,CAAC,EAAE,MAAA,EAAQ,KAAA,EAAM,KACvE,OAAO,IAAA,CAAK,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE;AACtD;ACvCA,IAAM,UAAA,GACJ,oMAAA;AACF,IAAM,QAAA,GAAW,oEAAA;AAUV,IAAM,KAAA,mBAAQ,MAAA,CAAA,CAAC,EAAE,KAAA,EAAO,aAAA,EAAe,QAAQ,SAAA,GAAY,EAAA,EAAI,GAAG,WAAA,EAAY,KAAc;AACjG,EAAA,kBAAA,EAAmB;AAEnB,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,CAAC,KAAA,KAAU,MAAM,KAAK,CAAA;AAClD,EAAA,MAAM,WAAA,GAAc,aAAA,CAAc,CAAC,KAAA,KAAU,MAAM,WAAW,CAAA;AAE9D,EAAA,MAAM,SAAS,KAAA,KAAU,MAAA;AACzB,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,MAAA,GAAS,MAAA,GAAS,OAAO,CAAA;AACnD,EAAA,MAAM,EAAE,OAAA,GAAU,uBAAA,EAAyB,SAAS,sBAAA,EAAuB,GAAI,UAAU,EAAC;AAE1F,EAAA,uBACE,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACE,GAAG,WAAA;AAAA,MACJ,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,WAAA;AAAA,MACT,YAAA,EAAY,SAAS,OAAA,GAAU,MAAA;AAAA,MAC/B,SAAA,EAAW,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,MAGrC,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,QAAK,IAAA,EAAM,KAAA,CAAM,QAAQ,SAAA,EAAW,CAAA,EAAG,QAAQ,CAAA,qBAAA,CAAA,EAAyB,CAAA;AAAA,wBACzE,GAAA,CAAC,QAAK,IAAA,EAAM,KAAA,CAAM,OAAO,SAAA,EAAW,CAAA,EAAG,QAAQ,CAAA,2BAAA,CAAA,EAA+B;AAAA;AAAA;AAAA,GAChF;AAEJ,CAAA,EAvBqB,OAAA","file":"index.js","sourcesContent":["import { addCollection, type IconifyJSON } from '@iconify/react';\n\n/*\n * The icons of the theme button. Iconify downloads an icon from its API the first time it is shown,\n * which cannot work offline and leaves the button empty until it arrives, so they are bundled here and\n * registered with Iconify (the same way as the toast icons, see `toast-icons.ts`).\n *\n * For each theme there are two: one that moves (`line-md`, drawn with SMIL and never stops) and a\n * still one (`solar`) for a person who asked for less motion.\n *\n * The data is what `https://api.iconify.design/<prefix>.json?icons=<name>` answers.\n */\nconst THEME_ICON_SETS: IconifyJSON[] = [\n {\n prefix: 'line-md',\n width: 24,\n height: 24,\n icons: {\n 'sunny-loop': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"><path stroke-dasharray=\"34\" d=\"M12 7c2.76 0 5 2.24 5 5c0 2.76 -2.24 5 -5 5c-2.76 0 -5 -2.24 -5 -5c0 -2.76 2.24 -5 5 -5Z\"><animate fill=\"freeze\" attributeName=\"stroke-dashoffset\" dur=\"0.4s\" values=\"34;0\"/></path><path d=\"M12 21v1M21 12h1M12 3v-1M3 12h-1\" opacity=\"0\"><animateTransform attributeName=\"transform\" dur=\"30s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\"/><set fill=\"freeze\" attributeName=\"opacity\" begin=\"0.5s\" to=\"1\"/><animate fill=\"freeze\" attributeName=\"d\" begin=\"0.5s\" dur=\"0.2s\" values=\"M12 19v1M19 12h1M12 5v-1M5 12h-1;M12 21v1M21 12h1M12 3v-1M3 12h-1\"/></path><path d=\"M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5\" opacity=\"0\"><animateTransform attributeName=\"transform\" dur=\"30s\" repeatCount=\"indefinite\" type=\"rotate\" values=\"0 12 12;360 12 12\"/><set fill=\"freeze\" attributeName=\"opacity\" begin=\"0.7s\" to=\"1\"/><animate fill=\"freeze\" attributeName=\"d\" begin=\"0.7s\" dur=\"0.2s\" values=\"M17 17l0.5 0.5M17 7l0.5 -0.5M7 7l-0.5 -0.5M7 17l-0.5 0.5;M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5\"/></path></g>',\n },\n 'moon-loop': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-dasharray=\"56\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M7 6c0 6.08 4.92 11 11 11c0.53 0 1.05 -0.04 1.56 -0.11c-1.61 2.47 -4.39 4.11 -7.56 4.11c-4.97 0 -9 -4.03 -9 -9c0 -3.17 1.64 -5.95 4.11 -7.56c-0.07 0.51 -0.11 1.03 -0.11 1.56Z\"><animate fill=\"freeze\" attributeName=\"stroke-dashoffset\" dur=\"0.6s\" values=\"56;0\"/></path><g fill=\"currentColor\"><path d=\"M15.22 6.03l2.53 -1.94l-3.19 -0.09l-1.06 -3l-1.06 3l-3.19 0.09l2.53 1.94l-0.91 3.06l2.63 -1.81l2.63 1.81l-0.91 -3.06Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"0.7s\" dur=\"6s\" keyTimes=\"0;0.1;0.4;0.5;1\" repeatCount=\"indefinite\" values=\"0;1;1;0;0\"/></path><path d=\"M19.61 12.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17l-0.59 -1.98Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"0.7s\" dur=\"6s\" keyTimes=\"0;0.2;0.3;0.6;0.7;1\" repeatCount=\"indefinite\" values=\"0;0;1;1;0;0\"/></path><path d=\"M13.61 5.25l1.64 -1.25l-2.06 -0.05l-0.69 -1.95l-0.69 1.95l-2.06 0.05l1.64 1.25l-0.59 1.98l1.7 -1.17l1.7 1.17Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"3.7s\" dur=\"6s\" keyTimes=\"0;0.1;0.4;0.5;1\" repeatCount=\"indefinite\" values=\"0;1;1;0;0\"/></path><path d=\"M20.83 9.73l1.88 -1.44l-2.37 -0.07l-0.79 -2.22l-0.79 2.23l-2.37 0.07l1.88 1.44l-0.68 2.27l1.95 -1.34l1.95 1.34Z\" opacity=\"0\"><animate attributeName=\"opacity\" begin=\"3.7s\" dur=\"6s\" keyTimes=\"0;0.2;0.3;0.6;0.7;1\" repeatCount=\"indefinite\" values=\"0;0;1;1;0;0\"/></path></g>',\n },\n },\n },\n {\n prefix: 'solar',\n width: 24,\n height: 24,\n icons: {\n 'sun-2-linear': {\n body: '<g fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-width=\"1.5\"><circle cx=\"12\" cy=\"12\" r=\"5\"/><path d=\"M12 2V4\"/><path d=\"M12 20V22\"/><path d=\"M4 12L2 12\"/><path d=\"M22 12L20 12\"/><path d=\"M19.7778 4.22266L17.5558 6.25424\"/><path d=\"M4.22217 4.22266L6.44418 6.25424\"/><path d=\"M6.44434 17.5557L4.22211 19.7779\"/><path d=\"M19.7778 19.7773L17.5558 17.5551\"/></g>',\n },\n 'moon-linear': {\n body: '<path fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"1.5\" d=\"M12 22C17.5228 22 22 17.5228 22 12C22 11.5373 21.3065 11.4608 21.0672 11.8568C19.9289 13.7406 17.8615 15 15.5 15C11.9101 15 9 12.0899 9 8.5C9 6.13845 10.2594 4.07105 12.1432 2.93276C12.5392 2.69347 12.4627 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z\"/>',\n },\n },\n },\n];\n\n/** What the button shows while the theme is dark (a sun: it would switch to light) and light (a moon). */\nexport const THEME_ICONS = {\n dark: { moving: 'line-md:sunny-loop', still: 'solar:sun-2-linear' },\n light: { moving: 'line-md:moon-loop', still: 'solar:moon-linear' },\n} as const;\n\nlet registered = false;\n\n/**\n * Registers the icons above with Iconify. `Theme` calls it when it renders, not when this file is\n * imported: an app that never renders the button never runs it, and nothing depends on the bundler\n * keeping an import that is only there for its effect (see `toast-icons.ts`). Calling it again is\n * harmless.\n */\nexport const registerThemeIcons = () => {\n if (registered) return;\n\n for (const iconSet of THEME_ICON_SETS) addCollection(iconSet);\n registered = true;\n};\n\n/** Every icon name registered above, e.g. `line-md:sunny-loop`. */\nexport const THEME_ICON_NAMES = THEME_ICON_SETS.flatMap(({ prefix, icons }) =>\n Object.keys(icons).map((name) => `${prefix}:${name}`),\n);\n","import type { TThemeStoreHook } from '@beautinique/frontend-stores';\nimport { Icon } from '@iconify/react';\nimport type { ComponentProps } from 'react';\n\nimport { registerThemeIcons, THEME_ICONS } from './theme-icons.js';\n\nexport interface ITheme extends Omit<\n ComponentProps<'button'>,\n 'children' | 'onClick' | 'type' | 'aria-label'\n> {\n /** The theme store of the app: what `createThemeStore()` of `@beautinique/frontend-stores` gave it. */\n store: TThemeStoreHook;\n /** What the button says to assistive technology, for the theme it would switch to. */\n labels?: {\n /** @default 'Switch to light theme' */\n toLight?: string;\n /** @default 'Switch to dark theme' */\n toDark?: string;\n };\n}\n\n// The hit area is bigger than the icon (the icon is 20px on a phone): the `after` box is a part of the\n// button, so a thumb that lands next to the icon still presses it, and nothing around it moves.\n// No `outline-hidden`: in Tailwind v4 it sets `--tw-outline-style: none`, which the\n// `focus-visible:outline-2` uses for its style, so the ring would never be drawn. A button only shows\n// the browser's own ring for the keyboard anyway (`:focus-visible`), never for a click.\nconst BUTTON_CSS =\n \"relative size-5 cursor-pointer rounded-full after:absolute after:-inset-1 after:content-[''] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-crayola-c md:size-6\";\nconst ICON_CSS = 'text-tertiary hover:text-secondary size-full [&_path]:stroke-[1.5]';\n\n/**\n * A button that switches between the dark and the light theme. It shows the theme it would switch\n * to: a sun while the theme is dark, a moon while it is light. It only changes the store; putting the\n * theme on the page (a class on `<html>`) is the app's.\n *\n * The icons move; for a person who asked their system for less motion (`prefers-reduced-motion`)\n * the button shows still ones instead.\n */\nexport const Theme = ({ store: useThemeStore, labels, className = '', ...buttonProps }: ITheme) => {\n registerThemeIcons();\n\n const theme = useThemeStore((state) => state.theme);\n const toggleTheme = useThemeStore((state) => state.toggleTheme);\n\n const isDark = theme === 'dark';\n const icons = THEME_ICONS[isDark ? 'dark' : 'light'];\n const { toLight = 'Switch to light theme', toDark = 'Switch to dark theme' } = labels ?? {};\n\n return (\n <button\n {...buttonProps}\n type=\"button\"\n onClick={toggleTheme}\n aria-label={isDark ? toLight : toDark}\n className={`${BUTTON_CSS} ${className}`}\n >\n {/* Both are in the page and css picks one: no script has to ask the system about motion. */}\n <Icon icon={icons.moving} className={`${ICON_CSS} motion-reduce:hidden`} />\n <Icon icon={icons.still} className={`${ICON_CSS} hidden motion-reduce:block`} />\n </button>\n );\n};\n"]}