@krizaka/ui 3.29.0 → 3.31.0

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 (403) hide show
  1. package/README.md +4 -8
  2. package/dist/action-bar.js +3 -3
  3. package/dist/action-bar.js.map +1 -1
  4. package/dist/argument-card.d.ts +1 -1
  5. package/dist/argument-card.js +2 -2
  6. package/dist/argument-card.js.map +1 -1
  7. package/dist/blocks.css +19 -60
  8. package/dist/{button-BmCrLCq7.d.ts → button-Cm9pFH3P.d.ts} +10 -9
  9. package/dist/button.d.ts +11 -10
  10. package/dist/button.js +1 -1
  11. package/dist/captcha.js +1 -1
  12. package/dist/card-grid.d.ts +5 -12
  13. package/dist/card-grid.js +4 -12
  14. package/dist/card-grid.js.map +1 -1
  15. package/dist/card.d.ts +7 -7
  16. package/dist/card.js +2 -2
  17. package/dist/card.js.map +1 -1
  18. package/dist/{chunk-OUWPBSSL.js → chunk-2AJ4NJUF.js} +8 -9
  19. package/dist/chunk-2AJ4NJUF.js.map +1 -0
  20. package/dist/{chunk-MQPC3P4T.js → chunk-2DGLWTPS.js} +3 -3
  21. package/dist/chunk-2DGLWTPS.js.map +1 -0
  22. package/dist/{chunk-DZU6RMYD.js → chunk-3DHNN5V7.js} +15 -9
  23. package/dist/chunk-3DHNN5V7.js.map +1 -0
  24. package/dist/{chunk-TFJDIOFK.js → chunk-4E5IUZHR.js} +3 -3
  25. package/dist/chunk-4E5IUZHR.js.map +1 -0
  26. package/dist/{chunk-HAQWKORZ.js → chunk-4JO5GSSD.js} +1 -37
  27. package/dist/chunk-4JO5GSSD.js.map +1 -0
  28. package/dist/{chunk-APNIVNIX.js → chunk-IBDTAMPF.js} +3 -4
  29. package/dist/chunk-IBDTAMPF.js.map +1 -0
  30. package/dist/{chunk-LYOPPBMC.js → chunk-KIBICUZK.js} +2 -2
  31. package/dist/{chunk-HBZPJ3EP.js → chunk-NJFCSVPT.js} +2 -2
  32. package/dist/{chunk-KM6VAKIE.js → chunk-RE5WJ4QP.js} +2 -2
  33. package/dist/chunk-RE5WJ4QP.js.map +1 -0
  34. package/dist/{chunk-CHOJUCVE.js → chunk-SJS6RJIT.js} +15 -9
  35. package/dist/chunk-SJS6RJIT.js.map +1 -0
  36. package/dist/{chunk-6ZYRUOTA.js → chunk-UV4HBVH7.js} +15 -9
  37. package/dist/chunk-UV4HBVH7.js.map +1 -0
  38. package/dist/command.js +2 -2
  39. package/dist/confirm-button.d.ts +1 -1
  40. package/dist/confirm-button.js +1 -1
  41. package/dist/continue-prompt.js +14 -8
  42. package/dist/continue-prompt.js.map +1 -1
  43. package/dist/data-table.js +2 -2
  44. package/dist/dialog.js +2 -2
  45. package/dist/engine-flow.d.ts +25 -2
  46. package/dist/engine-flow.js +27 -6
  47. package/dist/engine-flow.js.map +1 -1
  48. package/dist/force-update-screen.js +2 -2
  49. package/dist/force-update-screen.js.map +1 -1
  50. package/dist/genui.js +3 -3
  51. package/dist/glow-card.d.ts +5 -4
  52. package/dist/glow-card.js +2 -8
  53. package/dist/glow-card.js.map +1 -1
  54. package/dist/image-cropper.js +1 -1
  55. package/dist/index.js +4 -4
  56. package/dist/index.js.map +1 -1
  57. package/dist/iso.d.ts +1 -1
  58. package/dist/iso.js.map +1 -1
  59. package/dist/landscape.js +4 -4
  60. package/dist/landscape.js.map +1 -1
  61. package/dist/link-card.d.ts +3 -6
  62. package/dist/link-card.js +1 -1
  63. package/dist/maintenance-screen.js +1 -1
  64. package/dist/map.d.ts +50 -5
  65. package/dist/map.js +202 -66
  66. package/dist/map.js.map +1 -1
  67. package/dist/match-dialog.js +1 -1
  68. package/dist/media-gallery.js +1 -1
  69. package/dist/media-gallery.js.map +1 -1
  70. package/dist/media-grid.js +2 -2
  71. package/dist/motion.css +52 -122
  72. package/dist/motion.d.ts +2 -2
  73. package/dist/motion.js +1 -1
  74. package/dist/native/map.js +64 -64
  75. package/dist/native/map.js.map +1 -1
  76. package/dist/native.js +30 -30
  77. package/dist/native.js.map +1 -1
  78. package/dist/nav-bar.d.ts +12 -3
  79. package/dist/nav-bar.js +19 -12
  80. package/dist/nav-bar.js.map +1 -1
  81. package/dist/pointer-light.d.ts +6 -9
  82. package/dist/pointer-light.js +9 -5
  83. package/dist/pointer-light.js.map +1 -1
  84. package/dist/radio-group.js +2 -2
  85. package/dist/radio-group.js.map +1 -1
  86. package/dist/service-card.js +1 -1
  87. package/dist/service-card.js.map +1 -1
  88. package/dist/site-footer.d.ts +1 -1
  89. package/dist/site-footer.js +2 -2
  90. package/dist/{sites-CHp_vELn.d.ts → sites-B4prB793.d.ts} +2 -2
  91. package/dist/sites.d.ts +2 -2
  92. package/dist/sites.js +6 -7
  93. package/dist/sites.js.map +1 -1
  94. package/dist/slider.js +1 -1
  95. package/dist/slider.js.map +1 -1
  96. package/dist/story.css +5 -12
  97. package/dist/theme.d.ts +1 -1
  98. package/dist/theme.js +1 -1
  99. package/dist/update-prompt.js +2 -2
  100. package/dist/update-prompt.js.map +1 -1
  101. package/dist/vertical-video.js +1 -1
  102. package/dist/video-player.js +2 -2
  103. package/dist/video-player.js.map +1 -1
  104. package/package.json +5 -5
  105. package/registry/action-bar.json +1 -1
  106. package/registry/app-shell.json +4 -4
  107. package/registry/argument-card.json +7 -16
  108. package/registry/auth-layout.json +4 -4
  109. package/registry/button.json +20 -20
  110. package/registry/card-grid.json +21 -24
  111. package/registry/card.json +7 -7
  112. package/registry/component-page.json +2 -2
  113. package/registry/confirm-button.json +6 -6
  114. package/registry/contact-page.json +2 -2
  115. package/registry/cover-hero.json +3 -3
  116. package/registry/dashboard-layout.json +2 -2
  117. package/registry/detail-layout.json +4 -4
  118. package/registry/docs-hub-page.json +2 -2
  119. package/registry/empty-state.json +1 -1
  120. package/registry/engine-flow.json +74 -3
  121. package/registry/examples/app-shell/admin-console.js +1 -1
  122. package/registry/examples/app-shell/admin-console.tsx +1 -1
  123. package/registry/examples/app-shell/basic.js +1 -1
  124. package/registry/examples/app-shell/basic.tsx +1 -1
  125. package/registry/examples/app-shell/desktop.js +1 -1
  126. package/registry/examples/app-shell/desktop.tsx +1 -1
  127. package/registry/examples/app-shell/orochia-studio.js +1 -1
  128. package/registry/examples/app-shell/orochia-studio.tsx +1 -1
  129. package/registry/examples/argument-card/hover-quiet.js +1 -1
  130. package/registry/examples/argument-card/hover-quiet.tsx +1 -1
  131. package/registry/examples/auth-layout/onboarding.js +2 -2
  132. package/registry/examples/auth-layout/onboarding.tsx +2 -2
  133. package/registry/examples/auth-layout/sign-in.js +2 -2
  134. package/registry/examples/auth-layout/sign-in.tsx +2 -2
  135. package/registry/examples/auth-layout/verify.js +1 -1
  136. package/registry/examples/auth-layout/verify.tsx +1 -1
  137. package/registry/examples/avatar/native/presence.dark.png +0 -0
  138. package/registry/examples/avatar/native/presence.light.png +0 -0
  139. package/registry/examples/badge/native/tones.dark.png +0 -0
  140. package/registry/examples/badge/native/tones.light.png +0 -0
  141. package/registry/examples/button/native/disabled.dark.png +0 -0
  142. package/registry/examples/button/native/disabled.light.png +0 -0
  143. package/registry/examples/button/native/gradient.dark.png +0 -0
  144. package/registry/examples/button/native/gradient.light.png +0 -0
  145. package/registry/examples/button/native/icon-only.dark.png +0 -0
  146. package/registry/examples/button/native/icon-only.light.png +0 -0
  147. package/registry/examples/button/native/icon.dark.png +0 -0
  148. package/registry/examples/button/native/icon.light.png +0 -0
  149. package/registry/examples/button/native/loading.dark.png +0 -0
  150. package/registry/examples/button/native/loading.light.png +0 -0
  151. package/registry/examples/button/native/primary.dark.png +0 -0
  152. package/registry/examples/button/native/primary.light.png +0 -0
  153. package/registry/examples/button/native/sizes.dark.png +0 -0
  154. package/registry/examples/button/native/sizes.light.png +0 -0
  155. package/registry/examples/button/signature.js +2 -2
  156. package/registry/examples/button/signature.tsx +4 -4
  157. package/registry/examples/card/interactive-link.tsx +1 -1
  158. package/registry/examples/card/native/body.dark.png +0 -0
  159. package/registry/examples/card/native/body.light.png +0 -0
  160. package/registry/examples/card/native/default.dark.png +0 -0
  161. package/registry/examples/card/native/default.light.png +0 -0
  162. package/registry/examples/card/native/elevated.dark.png +0 -0
  163. package/registry/examples/card/native/elevated.light.png +0 -0
  164. package/registry/examples/card-grid/hover-quiet.js +1 -1
  165. package/registry/examples/card-grid/hover-quiet.tsx +1 -1
  166. package/registry/examples/chat/native/assistant.dark.png +0 -0
  167. package/registry/examples/chat/native/assistant.light.png +0 -0
  168. package/registry/examples/chat/native/conversation.dark.png +0 -0
  169. package/registry/examples/chat/native/conversation.light.png +0 -0
  170. package/registry/examples/chat/native/inbox.dark.png +0 -0
  171. package/registry/examples/chat/native/inbox.light.png +0 -0
  172. package/registry/examples/checkbox/native/terms.dark.png +0 -0
  173. package/registry/examples/checkbox/native/terms.light.png +0 -0
  174. package/registry/examples/chip/native/multiple.dark.png +0 -0
  175. package/registry/examples/chip/native/multiple.light.png +0 -0
  176. package/registry/examples/chip/native/single.dark.png +0 -0
  177. package/registry/examples/chip/native/single.light.png +0 -0
  178. package/registry/examples/chip/native/toggle.dark.png +0 -0
  179. package/registry/examples/chip/native/toggle.light.png +0 -0
  180. package/registry/examples/component-page/button.js +2 -2
  181. package/registry/examples/component-page/button.tsx +2 -2
  182. package/registry/examples/contact-page/team.js +1 -1
  183. package/registry/examples/contact-page/team.tsx +1 -1
  184. package/registry/examples/cover-hero/plain.js +1 -1
  185. package/registry/examples/cover-hero/plain.tsx +1 -1
  186. package/registry/examples/cover-hero/shop.js +1 -1
  187. package/registry/examples/cover-hero/shop.tsx +1 -1
  188. package/registry/examples/dashboard-layout/orazaka-eric.js +2 -2
  189. package/registry/examples/dashboard-layout/orazaka-eric.tsx +2 -2
  190. package/registry/examples/date-picker/native/calendar.dark.png +0 -0
  191. package/registry/examples/date-picker/native/calendar.light.png +0 -0
  192. package/registry/examples/date-picker/native/day-strip.dark.png +0 -0
  193. package/registry/examples/date-picker/native/day-strip.light.png +0 -0
  194. package/registry/examples/date-picker/native/month-year.dark.png +0 -0
  195. package/registry/examples/date-picker/native/month-year.light.png +0 -0
  196. package/registry/examples/date-picker/native/time-slots.dark.png +0 -0
  197. package/registry/examples/date-picker/native/time-slots.light.png +0 -0
  198. package/registry/examples/description-list/native/job-details.dark.png +0 -0
  199. package/registry/examples/description-list/native/job-details.light.png +0 -0
  200. package/registry/examples/detail-layout/checkout.js +1 -1
  201. package/registry/examples/detail-layout/checkout.tsx +1 -1
  202. package/registry/examples/detail-layout/job.js +1 -1
  203. package/registry/examples/detail-layout/job.tsx +1 -1
  204. package/registry/examples/detail-layout/video.js +2 -2
  205. package/registry/examples/detail-layout/video.tsx +2 -2
  206. package/registry/examples/dialog/native/sheet.dark.png +0 -0
  207. package/registry/examples/dialog/native/sheet.light.png +0 -0
  208. package/registry/examples/docs-hub-page/krizaka.js +1 -1
  209. package/registry/examples/docs-hub-page/krizaka.tsx +1 -1
  210. package/registry/examples/empty-state/library.js +1 -1
  211. package/registry/examples/empty-state/library.tsx +1 -1
  212. package/registry/examples/empty-state/native/default.dark.png +0 -0
  213. package/registry/examples/empty-state/native/default.light.png +0 -0
  214. package/registry/examples/fab/native/extended.dark.png +0 -0
  215. package/registry/examples/fab/native/extended.light.png +0 -0
  216. package/registry/examples/force-update-screen/native/default.dark.png +0 -0
  217. package/registry/examples/force-update-screen/native/default.light.png +0 -0
  218. package/registry/examples/form/native/amount.dark.png +0 -0
  219. package/registry/examples/form/native/amount.light.png +0 -0
  220. package/registry/examples/form/native/audience.dark.png +0 -0
  221. package/registry/examples/form/native/audience.light.png +0 -0
  222. package/registry/examples/form/native/profile.dark.png +0 -0
  223. package/registry/examples/form/native/profile.light.png +0 -0
  224. package/registry/examples/form/native/settings.dark.png +0 -0
  225. package/registry/examples/form/native/settings.light.png +0 -0
  226. package/registry/examples/form/native/sign-up.dark.png +0 -0
  227. package/registry/examples/form/native/sign-up.light.png +0 -0
  228. package/registry/examples/form/native/upload.dark.png +0 -0
  229. package/registry/examples/form/native/upload.light.png +0 -0
  230. package/registry/examples/glow-card/spotlight.tsx +1 -1
  231. package/registry/examples/goal-gauge/native/default.dark.png +0 -0
  232. package/registry/examples/goal-gauge/native/default.light.png +0 -0
  233. package/registry/examples/landing-page/krizaka.js +3 -3
  234. package/registry/examples/landing-page/krizaka.tsx +3 -3
  235. package/registry/examples/link-card/hover-quiet.js +1 -1
  236. package/registry/examples/link-card/hover-quiet.tsx +1 -1
  237. package/registry/examples/loader/native/block.dark.png +0 -0
  238. package/registry/examples/loader/native/block.light.png +0 -0
  239. package/registry/examples/map/native/location-picker.dark.png +0 -0
  240. package/registry/examples/map/native/location-picker.light.png +0 -0
  241. package/registry/examples/map/route.js +36 -0
  242. package/registry/examples/map/route.tsx +35 -0
  243. package/registry/examples/marketing-layout/pricing.js +1 -1
  244. package/registry/examples/marketing-layout/pricing.tsx +1 -1
  245. package/registry/examples/marketing-layout/product-page.js +1 -1
  246. package/registry/examples/marketing-layout/product-page.tsx +2 -2
  247. package/registry/examples/mascot-state/native/default.dark.png +0 -0
  248. package/registry/examples/mascot-state/native/default.light.png +0 -0
  249. package/registry/examples/mascots/native/crane.dark.png +0 -0
  250. package/registry/examples/mascots/native/crane.light.png +0 -0
  251. package/registry/examples/mascots/native/default.dark.png +0 -0
  252. package/registry/examples/mascots/native/default.light.png +0 -0
  253. package/registry/examples/mascots/native/lovebird.dark.png +0 -0
  254. package/registry/examples/mascots/native/lovebird.light.png +0 -0
  255. package/registry/examples/mascots/native/phoenix.dark.png +0 -0
  256. package/registry/examples/mascots/native/phoenix.light.png +0 -0
  257. package/registry/examples/match-dialog/native/its-a-match.dark.png +0 -0
  258. package/registry/examples/match-dialog/native/its-a-match.light.png +0 -0
  259. package/registry/examples/media-capture/native/photo.dark.png +0 -0
  260. package/registry/examples/media-capture/native/photo.light.png +0 -0
  261. package/registry/examples/meta-row/native/video.dark.png +0 -0
  262. package/registry/examples/meta-row/native/video.light.png +0 -0
  263. package/registry/examples/meter/native/credits.dark.png +0 -0
  264. package/registry/examples/meter/native/credits.light.png +0 -0
  265. package/registry/examples/meter/native/split-ring.dark.png +0 -0
  266. package/registry/examples/meter/native/split-ring.light.png +0 -0
  267. package/registry/examples/nav-bar/family-product.js +1 -1
  268. package/registry/examples/nav-bar/family-product.tsx +1 -1
  269. package/registry/examples/onboarding/native/first-launch.dark.png +0 -0
  270. package/registry/examples/onboarding/native/first-launch.light.png +0 -0
  271. package/registry/examples/permission-prompt/native/blocked.dark.png +0 -0
  272. package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
  273. package/registry/examples/permission-prompt/native/camera.dark.png +0 -0
  274. package/registry/examples/permission-prompt/native/camera.light.png +0 -0
  275. package/registry/examples/photo-grid/native/profile-photos.dark.png +0 -0
  276. package/registry/examples/photo-grid/native/profile-photos.light.png +0 -0
  277. package/registry/examples/pricing-page/credits.js +3 -3
  278. package/registry/examples/pricing-page/credits.tsx +3 -3
  279. package/registry/examples/product-page/orazaka.js +2 -2
  280. package/registry/examples/product-page/orazaka.tsx +2 -2
  281. package/registry/examples/profile-card/native/default.dark.png +0 -0
  282. package/registry/examples/profile-card/native/default.light.png +0 -0
  283. package/registry/examples/progress/native/bar.dark.png +0 -0
  284. package/registry/examples/progress/native/bar.light.png +0 -0
  285. package/registry/examples/progress/native/indeterminate.dark.png +0 -0
  286. package/registry/examples/progress/native/indeterminate.light.png +0 -0
  287. package/registry/examples/progress/native/ring.dark.png +0 -0
  288. package/registry/examples/progress/native/ring.light.png +0 -0
  289. package/registry/examples/radio-group/native/buttons.dark.png +0 -0
  290. package/registry/examples/radio-group/native/buttons.light.png +0 -0
  291. package/registry/examples/radio-group/native/cards.dark.png +0 -0
  292. package/registry/examples/radio-group/native/cards.light.png +0 -0
  293. package/registry/examples/radio-group/native/list.dark.png +0 -0
  294. package/registry/examples/radio-group/native/list.light.png +0 -0
  295. package/registry/examples/screen/native/auth.dark.png +0 -0
  296. package/registry/examples/screen/native/auth.light.png +0 -0
  297. package/registry/examples/screen/native/chat.dark.png +0 -0
  298. package/registry/examples/screen/native/chat.light.png +0 -0
  299. package/registry/examples/screen/native/profile.dark.png +0 -0
  300. package/registry/examples/screen/native/profile.light.png +0 -0
  301. package/registry/examples/screen/native/settings.dark.png +0 -0
  302. package/registry/examples/screen/native/settings.light.png +0 -0
  303. package/registry/examples/search-field/native/cancel.dark.png +0 -0
  304. package/registry/examples/search-field/native/cancel.light.png +0 -0
  305. package/registry/examples/settings-layout/account.js +1 -1
  306. package/registry/examples/settings-layout/account.tsx +1 -1
  307. package/registry/examples/settings-layout/native/account.dark.png +0 -0
  308. package/registry/examples/settings-layout/native/account.light.png +0 -0
  309. package/registry/examples/settings-layout/sections.js +1 -1
  310. package/registry/examples/settings-layout/sections.tsx +1 -1
  311. package/registry/examples/showcase/native/slides.dark.png +0 -0
  312. package/registry/examples/showcase/native/slides.light.png +0 -0
  313. package/registry/examples/slider/native/default.dark.png +0 -0
  314. package/registry/examples/slider/native/default.light.png +0 -0
  315. package/registry/examples/slider/native/range.dark.png +0 -0
  316. package/registry/examples/slider/native/range.light.png +0 -0
  317. package/registry/examples/slider/native/stepped.dark.png +0 -0
  318. package/registry/examples/slider/native/stepped.light.png +0 -0
  319. package/registry/examples/slider/native/vertical.dark.png +0 -0
  320. package/registry/examples/slider/native/vertical.light.png +0 -0
  321. package/registry/examples/spinner/native/sizes.dark.png +0 -0
  322. package/registry/examples/spinner/native/sizes.light.png +0 -0
  323. package/registry/examples/split-view/messages.js +1 -1
  324. package/registry/examples/split-view/messages.tsx +1 -1
  325. package/registry/examples/status-page/building.js +1 -1
  326. package/registry/examples/status-page/building.tsx +1 -1
  327. package/registry/examples/step-progress/native/sign-up.dark.png +0 -0
  328. package/registry/examples/step-progress/native/sign-up.light.png +0 -0
  329. package/registry/examples/stepper/native/run.dark.png +0 -0
  330. package/registry/examples/stepper/native/run.light.png +0 -0
  331. package/registry/examples/sticky-action/phone.js +1 -1
  332. package/registry/examples/sticky-action/phone.tsx +1 -1
  333. package/registry/examples/switch/native/default.dark.png +0 -0
  334. package/registry/examples/switch/native/default.light.png +0 -0
  335. package/registry/examples/switch/native/settings.dark.png +0 -0
  336. package/registry/examples/switch/native/settings.light.png +0 -0
  337. package/registry/examples/tab-bar/native/main-sections.dark.png +0 -0
  338. package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
  339. package/registry/examples/tabs/native/sections.dark.png +0 -0
  340. package/registry/examples/tabs/native/sections.light.png +0 -0
  341. package/registry/examples/tag-selector/native/interests.dark.png +0 -0
  342. package/registry/examples/tag-selector/native/interests.light.png +0 -0
  343. package/registry/examples/toast/native/snackbar.dark.png +0 -0
  344. package/registry/examples/toast/native/snackbar.light.png +0 -0
  345. package/registry/examples/toast/native/tones.dark.png +0 -0
  346. package/registry/examples/toast/native/tones.light.png +0 -0
  347. package/registry/examples/txt/native/tones.dark.png +0 -0
  348. package/registry/examples/txt/native/tones.light.png +0 -0
  349. package/registry/examples/update-prompt/native/default.dark.png +0 -0
  350. package/registry/examples/update-prompt/native/default.light.png +0 -0
  351. package/registry/examples/verified-badge/native/verified.dark.png +0 -0
  352. package/registry/examples/verified-badge/native/verified.light.png +0 -0
  353. package/registry/examples/vertical-video/native/rail.dark.png +0 -0
  354. package/registry/examples/vertical-video/native/rail.light.png +0 -0
  355. package/registry/examples/waveform/native/card.dark.png +0 -0
  356. package/registry/examples/waveform/native/card.light.png +0 -0
  357. package/registry/force-update-screen.json +1 -1
  358. package/registry/form.json +6 -6
  359. package/registry/glow-card.json +19 -19
  360. package/registry/index.json +20 -21
  361. package/registry/iso.json +7 -7
  362. package/registry/landing-page.json +2 -2
  363. package/registry/landscape.json +1 -1
  364. package/registry/link-card.json +15 -24
  365. package/registry/map.json +235 -6
  366. package/registry/marketing-layout.json +3 -3
  367. package/registry/media-gallery.json +1 -1
  368. package/registry/nav-bar.json +32 -4
  369. package/registry/pointer-light.json +17 -22
  370. package/registry/pricing-page.json +2 -2
  371. package/registry/product-page.json +2 -2
  372. package/registry/progress.json +2 -2
  373. package/registry/radio-group.json +1 -1
  374. package/registry/rail-nav.json +2 -2
  375. package/registry/service-card.json +1 -1
  376. package/registry/settings-layout.json +3 -3
  377. package/registry/site-footer.json +2 -2
  378. package/registry/sites.json +1 -1
  379. package/registry/slider.json +1 -1
  380. package/registry/split-view.json +2 -2
  381. package/registry/status-page.json +1 -1
  382. package/registry/sticky-action.json +2 -2
  383. package/registry/update-prompt.json +1 -1
  384. package/registry/video-player.json +1 -1
  385. package/dist/chunk-6ZYRUOTA.js.map +0 -1
  386. package/dist/chunk-AB5D3KBG.js +0 -37
  387. package/dist/chunk-AB5D3KBG.js.map +0 -1
  388. package/dist/chunk-APNIVNIX.js.map +0 -1
  389. package/dist/chunk-CHOJUCVE.js.map +0 -1
  390. package/dist/chunk-DZU6RMYD.js.map +0 -1
  391. package/dist/chunk-HAQWKORZ.js.map +0 -1
  392. package/dist/chunk-KM6VAKIE.js.map +0 -1
  393. package/dist/chunk-MQPC3P4T.js.map +0 -1
  394. package/dist/chunk-OUWPBSSL.js.map +0 -1
  395. package/dist/chunk-TFJDIOFK.js.map +0 -1
  396. package/registry/examples/argument-card/hover-light.js +0 -17
  397. package/registry/examples/argument-card/hover-light.tsx +0 -19
  398. package/registry/examples/link-card/hover-light.d.ts +0 -4
  399. package/registry/examples/link-card/hover-light.js +0 -18
  400. package/registry/examples/link-card/hover-light.tsx +0 -20
  401. /package/dist/{chunk-LYOPPBMC.js.map → chunk-KIBICUZK.js.map} +0 -0
  402. /package/dist/{chunk-HBZPJ3EP.js.map → chunk-NJFCSVPT.js.map} +0 -0
  403. /package/registry/examples/{argument-card/hover-light.d.ts → map/route.d.ts} +0 -0
package/dist/sites.js CHANGED
@@ -7,9 +7,8 @@ var sites = [
7
7
  site({ id: "yasakia", name: "Yasakia", url: "https://dev.yasakia.com", kind: "product", group: "products", status: "development", mark: "yasakia", repo: "https://github.com/krizaka/yasakia" }),
8
8
  site({ id: "yororis", name: "Yororis", url: "https://dev.yororis.com", kind: "product", group: "products", status: "construction", mark: "yororis", repo: "https://github.com/krizaka/yororis" }),
9
9
  site({ id: "yomizaka", name: "Yomizaka", url: "https://dev.yomizaka.com", kind: "product", group: "products", status: "development", mark: "yomizaka", repo: "https://github.com/krizaka/yomizaka" }),
10
- // In development: nothing deployed yet, so the address is the repository (never a dead link to an unborn dev site).
11
- site({ id: "kachizaka", name: "Kachizaka", url: "https://github.com/krizaka/kachizaka", kind: "product", group: "products", status: "development", mark: "kachizaka", repo: "https://github.com/krizaka/kachizaka" }),
12
- site({ id: "akinaza", name: "Akinaza", url: "https://github.com/krizaka/akinaza", kind: "product", group: "products", status: "development", mark: "akinaza", repo: "https://github.com/krizaka/akinaza" }),
10
+ site({ id: "kachizaka", name: "Kachizaka", url: "https://dev.kachizaka.com", kind: "product", group: "products", status: "development", mark: "kachizaka", repo: "https://github.com/krizaka/kachizaka" }),
11
+ site({ id: "akinaza", name: "Akinaza", url: "https://dev.akinaza.com", kind: "product", group: "products", status: "development", mark: "akinaza", repo: "https://github.com/krizaka/akinaza" }),
13
12
  site({ id: "ui", name: "Krizaka UI", url: "https://ui.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-ui" }),
14
13
  site({ id: "java", name: "Krizaka Java", url: "https://java.krizaka.com", kind: "open-source", group: "open-source", status: "released", mark: "krizaka", repo: "https://github.com/krizaka/krizaka-build" }),
15
14
  site({ id: "github", name: "GitHub", url: "https://github.com/krizaka", kind: "open-source", group: "github", status: "released", mark: "github", repo: "https://github.com/krizaka" })
@@ -31,9 +30,9 @@ var familyLabels = {
31
30
  current: "You are here",
32
31
  descriptions: {
33
32
  krizaka: "The company: our products, our open source, our story.",
34
- orazaka: "Sovereign AI, on your own servers.",
33
+ orazaka: "Sovereign AI on your own servers: chat, documents, images and video \u2014 and the engine under the other products.",
35
34
  orochia: "A video platform for creators.",
36
- yasakia: "The dating app where you talk first.",
35
+ yasakia: "Meet real people: introductions, and photos checked before you see them.",
37
36
  yororis: "A listening space with a face and a voice.",
38
37
  yomizaka: "Yomizaka reads your leases, contracts and invoices.",
39
38
  kachizaka: "Predictions among friends \u2014 live data, in real time.",
@@ -53,9 +52,9 @@ var familyLabels = {
53
52
  current: "Vous \xEAtes ici",
54
53
  descriptions: {
55
54
  krizaka: "La compagnie : nos produits, notre open source, notre histoire.",
56
- orazaka: "L\u2019IA souveraine, sur vos propres serveurs.",
55
+ orazaka: "L\u2019IA souveraine sur vos propres serveurs : conversation, documents, images et vid\xE9o \u2014 et le moteur des autres produits.",
57
56
  orochia: "Une plateforme vid\xE9o pour les cr\xE9ateurs.",
58
- yasakia: "L\u2019app de rencontre o\xF9 l\u2019on se parle d\u2019abord.",
57
+ yasakia: "Rencontrez de vraies personnes : des pr\xE9sentations, et des photos v\xE9rifi\xE9es avant que vous les voyiez.",
59
58
  yororis: "Un espace d\u2019\xE9coute avec un visage et une voix.",
60
59
  yomizaka: "Yomizaka lit vos baux, contrats et factures.",
61
60
  kachizaka: "Les pronostics entre amis \u2014 des donn\xE9es en direct.",
package/dist/sites.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sites/sites.ts"],"sourcesContent":["// Server-safe: plain data. The Krizaka family — every site Krizaka runs, once. The family switcher of the bar\n// (`NavBar.Family`) and the common footer (`SiteFooter`) both read it, so adding a site is one release of this package:\n// every bar and every footer of the family follow.\n//\n// The words of the family (a site's one line, the groups, the statuses, the footer's signature) are brand data, written\n// here in English and French (`familyLabels`) — a site passes the set of its locale, or its own translation.\n\n/** A site of the family. */\nexport type SiteId = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"ui\" | \"java\" | \"github\";\n\n/** What a site is: the company, a product, or an open-source project. It chooses the footer's signature line. */\nexport type SiteKind = \"company\" | \"product\" | \"open-source\";\n\n/**\n * `released`: open to visit. `upcoming`: announced, not released yet (said \"Coming soon\"). `construction`: under\n * construction — nothing deployed beyond its page, nothing offered. `development`: being built in the open, nothing\n * deployed yet — its address is its repository (said \"In development\").\n */\nexport type SiteStatus = \"released\" | \"upcoming\" | \"construction\" | \"development\";\n\n/** The groups of the family, in reading order: Krizaka · Products · Open source · GitHub. */\nexport type SiteGroup = \"krizaka\" | \"products\" | \"open-source\" | \"github\";\n\n/** The mark a site wears: a brand of `ProductLogo` (Krizaka UI and Krizaka Java wear Krizaka's), or GitHub's. */\nexport type SiteMark = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"github\";\n\nexport interface Site {\n readonly id: SiteId;\n /** The name, never translated. */\n readonly name: string;\n /** The address of the site (its home). */\n readonly url: string;\n /** The address without the scheme, as people say it (`ui.krizaka.com`). */\n readonly host: string;\n readonly kind: SiteKind;\n readonly group: SiteGroup;\n readonly status: SiteStatus;\n readonly mark: SiteMark;\n /** The repository the site is built from. */\n readonly repo: string;\n}\n\nconst site = (s: Omit<Site, \"host\">): Site => ({ ...s, host: s.url.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\") });\n\n/** Every site of the family, in reading order (the group order, then the order inside each group). */\nexport const sites: readonly Site[] = [\n site({ id: \"krizaka\", name: \"Krizaka\", url: \"https://www.krizaka.com\", kind: \"company\", group: \"krizaka\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-com\" }),\n site({ id: \"orazaka\", name: \"Orazaka\", url: \"https://dev.orazaka.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orazaka\", repo: \"https://github.com/krizaka/orazaka\" }),\n site({ id: \"orochia\", name: \"Orochia\", url: \"https://dev.orochia.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orochia\", repo: \"https://github.com/krizaka/orochia\" }),\n site({ id: \"yasakia\", name: \"Yasakia\", url: \"https://dev.yasakia.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yasakia\", repo: \"https://github.com/krizaka/yasakia\" }),\n site({ id: \"yororis\", name: \"Yororis\", url: \"https://dev.yororis.com\", kind: \"product\", group: \"products\", status: \"construction\", mark: \"yororis\", repo: \"https://github.com/krizaka/yororis\" }),\n site({ id: \"yomizaka\", name: \"Yomizaka\", url: \"https://dev.yomizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yomizaka\", repo: \"https://github.com/krizaka/yomizaka\" }),\n // In development: nothing deployed yet, so the address is the repository (never a dead link to an unborn dev site).\n site({ id: \"kachizaka\", name: \"Kachizaka\", url: \"https://github.com/krizaka/kachizaka\", kind: \"product\", group: \"products\", status: \"development\", mark: \"kachizaka\", repo: \"https://github.com/krizaka/kachizaka\" }),\n site({ id: \"akinaza\", name: \"Akinaza\", url: \"https://github.com/krizaka/akinaza\", kind: \"product\", group: \"products\", status: \"development\", mark: \"akinaza\", repo: \"https://github.com/krizaka/akinaza\" }),\n site({ id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-ui\" }),\n site({ id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-build\" }),\n site({ id: \"github\", name: \"GitHub\", url: \"https://github.com/krizaka\", kind: \"open-source\", group: \"github\", status: \"released\", mark: \"github\", repo: \"https://github.com/krizaka\" }),\n];\n\n/** The groups, in reading order. */\nexport const siteGroups: readonly SiteGroup[] = [\"krizaka\", \"products\", \"open-source\", \"github\"];\n\n/** A site by id. */\nexport function siteById(id: SiteId): Site {\n const found = sites.find((s) => s.id === id);\n if (!found) throw new Error(`Unknown Krizaka site \"${id}\".`);\n return found;\n}\n\n/** The family grouped, in reading order: `[{ group, sites }]`, empty groups left out. */\nexport function sitesByGroup(): { group: SiteGroup; sites: Site[] }[] {\n return siteGroups.map((group) => ({ group, sites: sites.filter((s) => s.group === group) })).filter((g) => g.sites.length > 0);\n}\n\n/** The languages the family's words are written in. */\nexport type SiteLocale = \"en\" | \"fr\";\n\n/** The words of the family: the switcher, the footer, each site's one line. */\nexport interface FamilyLabels {\n /** The family's name: the switcher's navigation and its button, the footer's navigation (“Krizaka family”). */\n family: string;\n /** The heading of each group. */\n groups: Record<SiteGroup, string>;\n /** The badge of a site that is not released. */\n status: Record<Exclude<SiteStatus, \"released\">, string>;\n /** Says which site is the current one (“You are here”). */\n current: string;\n /** One line per site: what it is. */\n descriptions: Record<SiteId, string>;\n /** The footer's signature, by the kind of the current site (“A Krizaka product”). */\n signature: Record<SiteKind, string>;\n /** The footer's place line (“Made in Montréal”). */\n place: string;\n /** The accessible name of the version (“Version”). */\n version: string;\n}\n\n/** The family's words in English and French. Pass `familyLabels[locale]`, or your own translation of the same shape. */\nexport const familyLabels: Record<SiteLocale, FamilyLabels> = {\n en: {\n family: \"Krizaka family\",\n groups: { krizaka: \"Krizaka\", products: \"Products\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Coming soon\", construction: \"Under construction\", development: \"In development\" },\n current: \"You are here\",\n descriptions: {\n krizaka: \"The company: our products, our open source, our story.\",\n orazaka: \"Sovereign AI, on your own servers.\",\n orochia: \"A video platform for creators.\",\n yasakia: \"The dating app where you talk first.\",\n yororis: \"A listening space with a face and a voice.\",\n yomizaka: \"Yomizaka reads your leases, contracts and invoices.\",\n kachizaka: \"Predictions among friends — live data, in real time.\",\n akinaza: \"Running a shop in Québec, for less — Loi 25 by design.\",\n ui: \"Components, tokens, icons and charts — web and React Native.\",\n java: \"Spring Boot building blocks on Maven Central.\",\n github: \"Every repository, in the open.\",\n },\n signature: { company: \"A Krizaka company\", product: \"A Krizaka product\", \"open-source\": \"A Krizaka open-source project\" },\n place: \"Made in Montréal\",\n version: \"Version\",\n },\n fr: {\n family: \"Famille Krizaka\",\n groups: { krizaka: \"Krizaka\", products: \"Produits\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Bientôt\", construction: \"En construction\", development: \"En développement\" },\n current: \"Vous êtes ici\",\n descriptions: {\n krizaka: \"La compagnie : nos produits, notre open source, notre histoire.\",\n orazaka: \"L’IA souveraine, sur vos propres serveurs.\",\n orochia: \"Une plateforme vidéo pour les créateurs.\",\n yasakia: \"L’app de rencontre où l’on se parle d’abord.\",\n yororis: \"Un espace d’écoute avec un visage et une voix.\",\n yomizaka: \"Yomizaka lit vos baux, contrats et factures.\",\n kachizaka: \"Les pronostics entre amis — des données en direct.\",\n akinaza: \"Tenir une boutique au Québec, pour moins cher — Loi 25 dès la conception.\",\n ui: \"Composants, jetons, icônes et graphiques — web et React Native.\",\n java: \"Des briques Spring Boot sur Maven Central.\",\n github: \"Tous les dépôts, au grand jour.\",\n },\n signature: { company: \"Une compagnie Krizaka\", product: \"Un produit Krizaka\", \"open-source\": \"Un projet open source de Krizaka\" },\n place: \"Fait à Montréal\",\n version: \"Version\",\n },\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/sites/sites.ts"],"sourcesContent":["// Server-safe: plain data. The Krizaka family — every site Krizaka runs, once. The family switcher of the bar\n// (`NavBar.Family`) and the common footer (`SiteFooter`) both read it, so adding a site is one release of this package:\n// every bar and every footer of the family follow.\n//\n// The words of the family (a site's one line, the groups, the statuses, the footer's signature) are brand data, written\n// here in English and French (`familyLabels`) — a site passes the set of its locale, or its own translation.\n\n/** A site of the family. */\nexport type SiteId = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"ui\" | \"java\" | \"github\";\n\n/** What a site is: the company, a product, or an open-source project. It chooses the footer's signature line. */\nexport type SiteKind = \"company\" | \"product\" | \"open-source\";\n\n/**\n * `released`: open to visit. `upcoming`: announced, not released yet (said \"Coming soon\"). `construction`: under\n * construction — nothing offered (a QA-only app may run; the public page says so). `development`: being built in the\n * open, with a dev site (said \"In development\"). A site with none yet would use its repository as its address.\n */\nexport type SiteStatus = \"released\" | \"upcoming\" | \"construction\" | \"development\";\n\n/** The groups of the family, in reading order: Krizaka · Products · Open source · GitHub. */\nexport type SiteGroup = \"krizaka\" | \"products\" | \"open-source\" | \"github\";\n\n/** The mark a site wears: a brand of `ProductLogo` (Krizaka UI and Krizaka Java wear Krizaka's), or GitHub's. */\nexport type SiteMark = \"krizaka\" | \"orazaka\" | \"orochia\" | \"yasakia\" | \"yororis\" | \"yomizaka\" | \"kachizaka\" | \"akinaza\" | \"github\";\n\nexport interface Site {\n readonly id: SiteId;\n /** The name, never translated. */\n readonly name: string;\n /** The address of the site (its home). */\n readonly url: string;\n /** The address without the scheme, as people say it (`ui.krizaka.com`). */\n readonly host: string;\n readonly kind: SiteKind;\n readonly group: SiteGroup;\n readonly status: SiteStatus;\n readonly mark: SiteMark;\n /** The repository the site is built from. */\n readonly repo: string;\n}\n\nconst site = (s: Omit<Site, \"host\">): Site => ({ ...s, host: s.url.replace(/^https?:\\/\\//, \"\").replace(/\\/$/, \"\") });\n\n/** Every site of the family, in reading order (the group order, then the order inside each group). */\nexport const sites: readonly Site[] = [\n site({ id: \"krizaka\", name: \"Krizaka\", url: \"https://www.krizaka.com\", kind: \"company\", group: \"krizaka\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-com\" }),\n site({ id: \"orazaka\", name: \"Orazaka\", url: \"https://dev.orazaka.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orazaka\", repo: \"https://github.com/krizaka/orazaka\" }),\n site({ id: \"orochia\", name: \"Orochia\", url: \"https://dev.orochia.com\", kind: \"product\", group: \"products\", status: \"released\", mark: \"orochia\", repo: \"https://github.com/krizaka/orochia\" }),\n site({ id: \"yasakia\", name: \"Yasakia\", url: \"https://dev.yasakia.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yasakia\", repo: \"https://github.com/krizaka/yasakia\" }),\n site({ id: \"yororis\", name: \"Yororis\", url: \"https://dev.yororis.com\", kind: \"product\", group: \"products\", status: \"construction\", mark: \"yororis\", repo: \"https://github.com/krizaka/yororis\" }),\n site({ id: \"yomizaka\", name: \"Yomizaka\", url: \"https://dev.yomizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"yomizaka\", repo: \"https://github.com/krizaka/yomizaka\" }),\n site({ id: \"kachizaka\", name: \"Kachizaka\", url: \"https://dev.kachizaka.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"kachizaka\", repo: \"https://github.com/krizaka/kachizaka\" }),\n site({ id: \"akinaza\", name: \"Akinaza\", url: \"https://dev.akinaza.com\", kind: \"product\", group: \"products\", status: \"development\", mark: \"akinaza\", repo: \"https://github.com/krizaka/akinaza\" }),\n site({ id: \"ui\", name: \"Krizaka UI\", url: \"https://ui.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-ui\" }),\n site({ id: \"java\", name: \"Krizaka Java\", url: \"https://java.krizaka.com\", kind: \"open-source\", group: \"open-source\", status: \"released\", mark: \"krizaka\", repo: \"https://github.com/krizaka/krizaka-build\" }),\n site({ id: \"github\", name: \"GitHub\", url: \"https://github.com/krizaka\", kind: \"open-source\", group: \"github\", status: \"released\", mark: \"github\", repo: \"https://github.com/krizaka\" }),\n];\n\n/** The groups, in reading order. */\nexport const siteGroups: readonly SiteGroup[] = [\"krizaka\", \"products\", \"open-source\", \"github\"];\n\n/** A site by id. */\nexport function siteById(id: SiteId): Site {\n const found = sites.find((s) => s.id === id);\n if (!found) throw new Error(`Unknown Krizaka site \"${id}\".`);\n return found;\n}\n\n/** The family grouped, in reading order: `[{ group, sites }]`, empty groups left out. */\nexport function sitesByGroup(): { group: SiteGroup; sites: Site[] }[] {\n return siteGroups.map((group) => ({ group, sites: sites.filter((s) => s.group === group) })).filter((g) => g.sites.length > 0);\n}\n\n/** The languages the family's words are written in. */\nexport type SiteLocale = \"en\" | \"fr\";\n\n/** The words of the family: the switcher, the footer, each site's one line. */\nexport interface FamilyLabels {\n /** The family's name: the switcher's navigation and its button, the footer's navigation (“Krizaka family”). */\n family: string;\n /** The heading of each group. */\n groups: Record<SiteGroup, string>;\n /** The badge of a site that is not released. */\n status: Record<Exclude<SiteStatus, \"released\">, string>;\n /** Says which site is the current one (“You are here”). */\n current: string;\n /** One line per site: what it is. */\n descriptions: Record<SiteId, string>;\n /** The footer's signature, by the kind of the current site (“A Krizaka product”). */\n signature: Record<SiteKind, string>;\n /** The footer's place line (“Made in Montréal”). */\n place: string;\n /** The accessible name of the version (“Version”). */\n version: string;\n}\n\n/** The family's words in English and French. Pass `familyLabels[locale]`, or your own translation of the same shape. */\nexport const familyLabels: Record<SiteLocale, FamilyLabels> = {\n en: {\n family: \"Krizaka family\",\n groups: { krizaka: \"Krizaka\", products: \"Products\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Coming soon\", construction: \"Under construction\", development: \"In development\" },\n current: \"You are here\",\n descriptions: {\n krizaka: \"The company: our products, our open source, our story.\",\n orazaka: \"Sovereign AI on your own servers: chat, documents, images and video — and the engine under the other products.\",\n orochia: \"A video platform for creators.\",\n yasakia: \"Meet real people: introductions, and photos checked before you see them.\",\n yororis: \"A listening space with a face and a voice.\",\n yomizaka: \"Yomizaka reads your leases, contracts and invoices.\",\n kachizaka: \"Predictions among friends — live data, in real time.\",\n akinaza: \"Running a shop in Québec, for less — Loi 25 by design.\",\n ui: \"Components, tokens, icons and charts — web and React Native.\",\n java: \"Spring Boot building blocks on Maven Central.\",\n github: \"Every repository, in the open.\",\n },\n signature: { company: \"A Krizaka company\", product: \"A Krizaka product\", \"open-source\": \"A Krizaka open-source project\" },\n place: \"Made in Montréal\",\n version: \"Version\",\n },\n fr: {\n family: \"Famille Krizaka\",\n groups: { krizaka: \"Krizaka\", products: \"Produits\", \"open-source\": \"Open source\", github: \"GitHub\" },\n status: { upcoming: \"Bientôt\", construction: \"En construction\", development: \"En développement\" },\n current: \"Vous êtes ici\",\n descriptions: {\n krizaka: \"La compagnie : nos produits, notre open source, notre histoire.\",\n orazaka: \"L’IA souveraine sur vos propres serveurs : conversation, documents, images et vidéo — et le moteur des autres produits.\",\n orochia: \"Une plateforme vidéo pour les créateurs.\",\n yasakia: \"Rencontrez de vraies personnes : des présentations, et des photos vérifiées avant que vous les voyiez.\",\n yororis: \"Un espace d’écoute avec un visage et une voix.\",\n yomizaka: \"Yomizaka lit vos baux, contrats et factures.\",\n kachizaka: \"Les pronostics entre amis — des données en direct.\",\n akinaza: \"Tenir une boutique au Québec, pour moins cher — Loi 25 dès la conception.\",\n ui: \"Composants, jetons, icônes et graphiques — web et React Native.\",\n java: \"Des briques Spring Boot sur Maven Central.\",\n github: \"Tous les dépôts, au grand jour.\",\n },\n signature: { company: \"Une compagnie Krizaka\", product: \"Un produit Krizaka\", \"open-source\": \"Un projet open source de Krizaka\" },\n place: \"Fait à Montréal\",\n version: \"Version\",\n },\n};\n"],"mappings":";AA0CA,IAAM,OAAO,CAAC,OAAiC,EAAE,GAAG,GAAG,MAAM,EAAE,IAAI,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,OAAO,EAAE,EAAE;AAG3G,IAAM,QAAyB;AAAA,EACpC,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,WAAW,QAAQ,YAAY,MAAM,WAAW,MAAM,yCAAyC,CAAC;AAAA,EAC/L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,YAAY,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC5L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,YAAY,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC5L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC/L,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,gBAAgB,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAChM,KAAK,EAAE,IAAI,YAAY,MAAM,YAAY,KAAK,4BAA4B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,YAAY,MAAM,sCAAsC,CAAC;AAAA,EACpM,KAAK,EAAE,IAAI,aAAa,MAAM,aAAa,KAAK,6BAA6B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,aAAa,MAAM,uCAAuC,CAAC;AAAA,EACzM,KAAK,EAAE,IAAI,WAAW,MAAM,WAAW,KAAK,2BAA2B,MAAM,WAAW,OAAO,YAAY,QAAQ,eAAe,MAAM,WAAW,MAAM,qCAAqC,CAAC;AAAA,EAC/L,KAAK,EAAE,IAAI,MAAM,MAAM,cAAc,KAAK,0BAA0B,MAAM,eAAe,OAAO,eAAe,QAAQ,YAAY,MAAM,WAAW,MAAM,wCAAwC,CAAC;AAAA,EACnM,KAAK,EAAE,IAAI,QAAQ,MAAM,gBAAgB,KAAK,4BAA4B,MAAM,eAAe,OAAO,eAAe,QAAQ,YAAY,MAAM,WAAW,MAAM,2CAA2C,CAAC;AAAA,EAC5M,KAAK,EAAE,IAAI,UAAU,MAAM,UAAU,KAAK,8BAA8B,MAAM,eAAe,OAAO,UAAU,QAAQ,YAAY,MAAM,UAAU,MAAM,6BAA6B,CAAC;AACxL;AAGO,IAAM,aAAmC,CAAC,WAAW,YAAY,eAAe,QAAQ;AAGxF,SAAS,SAAS,IAAkB;AACzC,QAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC3C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,yBAAyB,EAAE,IAAI;AAC3D,SAAO;AACT;AAGO,SAAS,eAAsD;AACpE,SAAO,WAAW,IAAI,CAAC,WAAW,EAAE,OAAO,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,SAAS,CAAC;AAC/H;AA0BO,IAAM,eAAiD;AAAA,EAC5D,IAAI;AAAA,IACF,QAAQ;AAAA,IACR,QAAQ,EAAE,SAAS,WAAW,UAAU,YAAY,eAAe,eAAe,QAAQ,SAAS;AAAA,IACnG,QAAQ,EAAE,UAAU,eAAe,cAAc,sBAAsB,aAAa,iBAAiB;AAAA,IACrG,SAAS;AAAA,IACT,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,WAAW,EAAE,SAAS,qBAAqB,SAAS,qBAAqB,eAAe,gCAAgC;AAAA,IACxH,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AAAA,EACA,IAAI;AAAA,IACF,QAAQ;AAAA,IACR,QAAQ,EAAE,SAAS,WAAW,UAAU,YAAY,eAAe,eAAe,QAAQ,SAAS;AAAA,IACnG,QAAQ,EAAE,UAAU,cAAW,cAAc,mBAAmB,aAAa,sBAAmB;AAAA,IAChG,SAAS;AAAA,IACT,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAW;AAAA,MACX,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,IACA,WAAW,EAAE,SAAS,yBAAyB,SAAS,sBAAsB,eAAe,mCAAmC;AAAA,IAChI,OAAO;AAAA,IACP,SAAS;AAAA,EACX;AACF;","names":[]}
package/dist/slider.js CHANGED
@@ -16,7 +16,7 @@ var slider = tv({
16
16
  control: "relative flex touch-none select-none items-center data-disabled:cursor-not-allowed data-disabled:opacity-40 data-[orientation=horizontal]:h-6 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:flex-col",
17
17
  track: "relative grow overflow-hidden rounded-full bg-surface-3 inset-shadow-well data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5",
18
18
  range: "absolute rounded-full data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full",
19
- thumb: "group/thumb relative block h-5 w-5 cursor-grab rounded-full border-2 border-accent bg-fg-on-media shadow-raised transition-[box-shadow,scale] duration-150 hover:scale-110 focus-visible:outline-hidden focus-visible:focus-ring active:scale-110 active:cursor-grabbing motion-reduce:transition-none motion-reduce:hover:scale-100 motion-reduce:active:scale-100",
19
+ thumb: "group/thumb relative block h-5 w-5 cursor-grab rounded-full border-2 border-accent bg-fg-on-media shadow-raised transition-[box-shadow,scale] duration-150 hover:ring-4 hover:ring-accent/15 focus-visible:outline-hidden focus-visible:focus-ring active:scale-110 active:cursor-grabbing motion-reduce:transition-none motion-reduce:active:scale-100",
20
20
  // The value over the thumb: shown while the thumb is hovered, focused or held.
21
21
  bubble: "pointer-events-none absolute bottom-full left-1/2 mb-2.5 -translate-x-1/2 whitespace-nowrap rounded-lg bg-fg px-2 py-1 font-mono text-[11px] font-semibold tabular-nums text-surface-0 opacity-0 shadow-floating transition-opacity duration-150 after:absolute after:left-1/2 after:top-full after:-translate-x-1/2 after:border-4 after:border-transparent after:border-t-fg group-hover/thumb:opacity-100 group-focus-visible/thumb:opacity-100 group-active/thumb:opacity-100 data-[always]:opacity-100 motion-reduce:transition-none",
22
22
  bubbleVertical: "bottom-auto left-full top-1/2 mb-0 ml-3 -translate-x-0 -translate-y-1/2 after:hidden",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/slider/slider.tsx"],"sourcesContent":["// Client. Radix Slider: role=\"slider\" on each thumb, arrows / Page Up / Page Down / Home / End, a range with two\n// thumbs, horizontal or vertical. The words arrive as props: `label` names the thumb(s), `formatValue` gives the\n// aria-valuetext and the value shown (above the track, or floating over the thumb while it is touched). `ticks` draws the\n// graduations of the steps (and `marks` their words under the track); `tone` fills with the brand's gradient or its\n// accent alone.\nimport { Slider as SliderPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { tv } from \"../tv\";\n\nexport const slider = tv({\n slots: {\n root: \"flex flex-col gap-2 data-[orientation=vertical]:h-full data-[orientation=vertical]:items-center\",\n header: \"flex items-baseline justify-between gap-3 text-xs font-semibold text-fg-secondary\",\n value: \"font-mono text-[11px] tabular-nums text-fg-secondary\",\n control:\n \"relative flex touch-none select-none items-center data-disabled:cursor-not-allowed data-disabled:opacity-40 \" +\n \"data-[orientation=horizontal]:h-6 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:flex-col\",\n track:\n \"relative grow overflow-hidden rounded-full bg-surface-3 inset-shadow-well \" +\n \"data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5\",\n range: \"absolute rounded-full data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full\",\n thumb:\n \"group/thumb relative block h-5 w-5 cursor-grab rounded-full border-2 border-accent bg-fg-on-media shadow-raised transition-[box-shadow,scale] duration-150 \" +\n \"hover:scale-110 focus-visible:outline-hidden focus-visible:focus-ring active:scale-110 active:cursor-grabbing motion-reduce:transition-none motion-reduce:hover:scale-100 motion-reduce:active:scale-100\",\n // The value over the thumb: shown while the thumb is hovered, focused or held.\n bubble:\n \"pointer-events-none absolute bottom-full left-1/2 mb-2.5 -translate-x-1/2 whitespace-nowrap rounded-lg bg-fg px-2 py-1 font-mono text-[11px] font-semibold tabular-nums text-surface-0 opacity-0 shadow-floating \" +\n \"transition-opacity duration-150 after:absolute after:left-1/2 after:top-full after:-translate-x-1/2 after:border-4 after:border-transparent after:border-t-fg \" +\n \"group-hover/thumb:opacity-100 group-focus-visible/thumb:opacity-100 group-active/thumb:opacity-100 data-[always]:opacity-100 motion-reduce:transition-none\",\n bubbleVertical: \"bottom-auto left-full top-1/2 mb-0 ml-3 -translate-x-0 -translate-y-1/2 after:hidden\",\n ticks: \"pointer-events-none absolute inset-0\",\n tick: \"absolute rounded-full bg-border-strong data-[on]:bg-on-accent/70 data-[orientation=horizontal]:top-1/2 data-[orientation=horizontal]:h-1 data-[orientation=horizontal]:w-px data-[orientation=horizontal]:-translate-x-1/2 data-[orientation=horizontal]:-translate-y-1/2 data-[orientation=vertical]:left-1/2 data-[orientation=vertical]:h-px data-[orientation=vertical]:w-1 data-[orientation=vertical]:-translate-x-1/2 data-[orientation=vertical]:translate-y-1/2\",\n marks: \"relative h-4 w-full text-[11px] font-medium tabular-nums text-fg-secondary\",\n mark: \"absolute top-0 -translate-x-1/2 whitespace-nowrap first:translate-x-0 last:-translate-x-full\",\n },\n variants: {\n tone: {\n /** The brand's signature: accent → accent-2, a glow under it. */\n gradient: { range: \"bg-linear-to-r from-accent to-accent-2 shadow-glow data-[orientation=vertical]:bg-linear-to-t\" },\n /** The accent alone. */\n solid: { range: \"bg-accent\" },\n },\n size: {\n md: {},\n lg: {\n track: \"data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5\",\n thumb: \"h-6 w-6\",\n control: \"data-[orientation=horizontal]:h-8 data-[orientation=vertical]:w-8\",\n },\n },\n },\n defaultVariants: { tone: \"gradient\", size: \"md\" },\n});\n\nexport type SliderValue = number | [number, number];\n\nexport type SliderMark = {\n /** Where the mark stands. */\n value: number;\n /** Its words under the track (\"0\", \"50 %\", \"Max\"), passed translated. */\n label: string;\n};\n\nexport type SliderProps<V extends SliderValue = number> = Omit<\n React.ComponentProps<typeof SliderPrimitive.Root>,\n \"value\" | \"defaultValue\" | \"onValueChange\" | \"onValueCommit\" | \"children\"\n> & {\n /** One number (a thumb) or two (a range). Controlled with `onValueChange`. */\n value?: V;\n /** The value at first, uncontrolled: one number, or two for a range. */\n defaultValue?: V;\n /** Called on every move, with one number or two. */\n onValueChange?: (value: V) => void;\n /** Called once the drag or the key press ends. */\n onValueCommit?: (value: V) => void;\n /** The accessible name — of the thumb, or of both thumbs of a range — passed translated. */\n label: string;\n /** For a range: each thumb's own name ([\"Minimum\", \"Maximum\"]), passed translated. */\n thumbLabels?: [string, string];\n /** The value as words (aria-valuetext) and as shown: \"1.5×\", \"−12 %\", \"3 min\". */\n formatValue?: (value: number) => string;\n /** Shows the label and the value above the track. Without it, `label` only names the thumb. */\n showLabel?: boolean;\n /** Shows the value floating over the thumb while it is hovered, focused or held (`\"always\"`: at all times). */\n floatingValue?: boolean | \"always\";\n /** Fills from this value instead of the minimum (a ±range from 0: brightness, balance). One horizontal thumb only. */\n origin?: number;\n /** Draws a graduation at every step (`true`, up to 40 of them) or at the values given. */\n ticks?: boolean | readonly number[];\n /** Words under the track at some values (`[{ value: 0, label: \"0\" }, { value: 100, label: \"100\" }]`). Horizontal only. */\n marks?: readonly SliderMark[];\n /**\n * `gradient` (the brand's accent → accent-2, a glow) or `solid` (the accent alone).\n * @default \"gradient\"\n */\n tone?: \"gradient\" | \"solid\";\n /**\n * md · lg (a thicker track and thumb: a hero control, a touch screen).\n * @default \"md\"\n */\n size?: \"md\" | \"lg\";\n};\n\nconst toArray = (v: SliderValue | undefined) => (v === undefined ? undefined : typeof v === \"number\" ? [v] : v);\n\n/** A slider on one value or a range: `value`/`defaultValue` + `onValueChange`, `min`, `max`, `step`, `orientation`. */\nexport function Slider<V extends SliderValue = number>({\n value,\n defaultValue,\n onValueChange,\n onValueCommit,\n label,\n thumbLabels,\n formatValue = String,\n showLabel,\n floatingValue,\n origin,\n ticks,\n marks,\n tone,\n size,\n min = 0,\n max = 100,\n step = 1,\n orientation = \"horizontal\",\n className,\n ...props\n}: SliderProps<V>) {\n const s = slider({ tone, size });\n const range = Array.isArray(value ?? defaultValue);\n const vertical = orientation === \"vertical\";\n const [inner, setInner] = React.useState(() => toArray(defaultValue) ?? [min]);\n const current = toArray(value) ?? inner;\n const out = (next: number[]) => (range ? next : next[0]) as V;\n const pct = (v: number) => ((v - min) / (max - min || 1)) * 100;\n const fill =\n origin !== undefined && !range && !vertical\n ? { left: `${Math.min(pct(origin), pct(current[0]!))}%`, right: `${100 - Math.max(pct(origin), pct(current[0]!))}%` }\n : undefined;\n const lo = range ? Math.min(...current) : (origin ?? min);\n const hi = range ? Math.max(...current) : current[0]!;\n const tickValues = ticks === true ? (max - min) / step <= 40 ? Array.from({ length: Math.round((max - min) / step) + 1 }, (_, i) => min + i * step) : [] : ticks ? [...ticks] : [];\n const id = React.useId();\n return (\n <div className={s.root({ className })} data-range={range ? \"\" : undefined} data-orientation={orientation}>\n {showLabel && (\n <div className={s.header()}>\n <span id={`${id}-label`}>{label}</span>\n <span className={s.value()} aria-hidden>\n {current.map(formatValue).join(\" – \")}\n </span>\n </div>\n )}\n <SliderPrimitive.Root\n min={min}\n max={max}\n step={step}\n orientation={orientation}\n value={current}\n onValueChange={(next) => {\n if (value === undefined) setInner(next);\n onValueChange?.(out(next));\n }}\n onValueCommit={onValueCommit && ((next) => onValueCommit(out(next)))}\n className={s.control()}\n {...props}\n >\n <SliderPrimitive.Track className={s.track()}>\n {fill ? <span data-origin=\"\" data-orientation={orientation} className={s.range()} style={fill} /> : <SliderPrimitive.Range className={s.range()} />}\n {tickValues.length ? (\n <span aria-hidden className={s.ticks()}>\n {tickValues.map((t) => (\n <span\n key={t}\n data-orientation={orientation}\n data-on={t > lo && t < hi ? \"\" : undefined}\n className={s.tick()}\n style={vertical ? { bottom: `${pct(t)}%` } : { left: `${pct(t)}%` }}\n />\n ))}\n </span>\n ) : null}\n </SliderPrimitive.Track>\n {current.map((v, i) => (\n <SliderPrimitive.Thumb\n key={i}\n aria-label={range ? (thumbLabels?.[i] ?? label) : showLabel ? undefined : label}\n aria-labelledby={!range && showLabel ? `${id}-label` : undefined}\n aria-valuetext={formatValue(v)}\n className={s.thumb()}\n >\n {floatingValue ? (\n <span aria-hidden data-always={floatingValue === \"always\" ? \"\" : undefined} className={s.bubble({ className: vertical ? s.bubbleVertical() : undefined })}>\n {formatValue(v)}\n </span>\n ) : null}\n </SliderPrimitive.Thumb>\n ))}\n </SliderPrimitive.Root>\n {marks?.length && !vertical ? (\n <div aria-hidden className={s.marks()}>\n {marks.map((m) => (\n <span key={m.value} className={s.mark()} style={{ left: `${pct(m.value)}%` }}>\n {m.label}\n </span>\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAKA,SAAS,UAAU,uBAAuB;AAC1C,YAAY,WAAW;AA6If,SACE,KADF;AAzID,IAAM,SAAS,GAAG;AAAA,EACvB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SACE;AAAA,IAEF,OACE;AAAA,IAEF,OAAO;AAAA,IACP,OACE;AAAA;AAAA,IAGF,QACE;AAAA,IAGF,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA;AAAA,MAEJ,UAAU,EAAE,OAAO,gGAAgG;AAAA;AAAA,MAEnH,OAAO,EAAE,OAAO,YAAY;AAAA,IAC9B;AAAA,IACA,MAAM;AAAA,MACJ,IAAI,CAAC;AAAA,MACL,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,MAAM,YAAY,MAAM,KAAK;AAClD,CAAC;AAmDD,IAAM,UAAU,CAAC,MAAgC,MAAM,SAAY,SAAY,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI;AAGtG,SAAS,OAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,cAAc;AAAA,EACd;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,QAAM,IAAI,OAAO,EAAE,MAAM,KAAK,CAAC;AAC/B,QAAM,QAAQ,MAAM,QAAQ,SAAS,YAAY;AACjD,QAAM,WAAW,gBAAgB;AACjC,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAS,MAAM,QAAQ,YAAY,KAAK,CAAC,GAAG,CAAC;AAC7E,QAAM,UAAU,QAAQ,KAAK,KAAK;AAClC,QAAM,MAAM,CAAC,SAAoB,QAAQ,OAAO,KAAK,CAAC;AACtD,QAAM,MAAM,CAAC,OAAgB,IAAI,QAAQ,MAAM,OAAO,KAAM;AAC5D,QAAM,OACJ,WAAW,UAAa,CAAC,SAAS,CAAC,WAC/B,EAAE,MAAM,GAAG,KAAK,IAAI,IAAI,MAAM,GAAG,IAAI,QAAQ,CAAC,CAAE,CAAC,CAAC,KAAK,OAAO,GAAG,MAAM,KAAK,IAAI,IAAI,MAAM,GAAG,IAAI,QAAQ,CAAC,CAAE,CAAC,CAAC,IAAI,IAClH;AACN,QAAM,KAAK,QAAQ,KAAK,IAAI,GAAG,OAAO,IAAK,UAAU;AACrD,QAAM,KAAK,QAAQ,KAAK,IAAI,GAAG,OAAO,IAAI,QAAQ,CAAC;AACnD,QAAM,aAAa,UAAU,QAAQ,MAAM,OAAO,QAAQ,KAAK,MAAM,KAAK,EAAE,QAAQ,KAAK,OAAO,MAAM,OAAO,IAAI,IAAI,EAAE,GAAG,CAAC,GAAG,MAAM,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,QAAQ,CAAC,GAAG,KAAK,IAAI,CAAC;AACjL,QAAM,KAAW,YAAM;AACvB,SACE,qBAAC,SAAI,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,cAAY,QAAQ,KAAK,QAAW,oBAAkB,aAC1F;AAAA,iBACC,qBAAC,SAAI,WAAW,EAAE,OAAO,GACvB;AAAA,0BAAC,UAAK,IAAI,GAAG,EAAE,UAAW,iBAAM;AAAA,MAChC,oBAAC,UAAK,WAAW,EAAE,MAAM,GAAG,eAAW,MACpC,kBAAQ,IAAI,WAAW,EAAE,KAAK,UAAK,GACtC;AAAA,OACF;AAAA,IAEF;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,eAAe,CAAC,SAAS;AACvB,cAAI,UAAU,OAAW,UAAS,IAAI;AACtC,0BAAgB,IAAI,IAAI,CAAC;AAAA,QAC3B;AAAA,QACA,eAAe,kBAAkB,CAAC,SAAS,cAAc,IAAI,IAAI,CAAC;AAAA,QAClE,WAAW,EAAE,QAAQ;AAAA,QACpB,GAAG;AAAA,QAEJ;AAAA,+BAAC,gBAAgB,OAAhB,EAAsB,WAAW,EAAE,MAAM,GACvC;AAAA,mBAAO,oBAAC,UAAK,eAAY,IAAG,oBAAkB,aAAa,WAAW,EAAE,MAAM,GAAG,OAAO,MAAM,IAAK,oBAAC,gBAAgB,OAAhB,EAAsB,WAAW,EAAE,MAAM,GAAG;AAAA,YAChJ,WAAW,SACV,oBAAC,UAAK,eAAW,MAAC,WAAW,EAAE,MAAM,GAClC,qBAAW,IAAI,CAAC,MACf;AAAA,cAAC;AAAA;AAAA,gBAEC,oBAAkB;AAAA,gBAClB,WAAS,IAAI,MAAM,IAAI,KAAK,KAAK;AAAA,gBACjC,WAAW,EAAE,KAAK;AAAA,gBAClB,OAAO,WAAW,EAAE,QAAQ,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI;AAAA;AAAA,cAJ7D;AAAA,YAKP,CACD,GACH,IACE;AAAA,aACN;AAAA,UACC,QAAQ,IAAI,CAAC,GAAG,MACf;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cAEC,cAAY,QAAS,cAAc,CAAC,KAAK,QAAS,YAAY,SAAY;AAAA,cAC1E,mBAAiB,CAAC,SAAS,YAAY,GAAG,EAAE,WAAW;AAAA,cACvD,kBAAgB,YAAY,CAAC;AAAA,cAC7B,WAAW,EAAE,MAAM;AAAA,cAElB,0BACC,oBAAC,UAAK,eAAW,MAAC,eAAa,kBAAkB,WAAW,KAAK,QAAW,WAAW,EAAE,OAAO,EAAE,WAAW,WAAW,EAAE,eAAe,IAAI,OAAU,CAAC,GACrJ,sBAAY,CAAC,GAChB,IACE;AAAA;AAAA,YAVC;AAAA,UAWP,CACD;AAAA;AAAA;AAAA,IACH;AAAA,IACC,OAAO,UAAU,CAAC,WACjB,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,MAAM,GACjC,gBAAM,IAAI,CAAC,MACV,oBAAC,UAAmB,WAAW,EAAE,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,IAAI,GACxE,YAAE,SADM,EAAE,KAEb,CACD,GACH,IACE;AAAA,KACN;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/slider/slider.tsx"],"sourcesContent":["// Client. Radix Slider: role=\"slider\" on each thumb, arrows / Page Up / Page Down / Home / End, a range with two\n// thumbs, horizontal or vertical. The words arrive as props: `label` names the thumb(s), `formatValue` gives the\n// aria-valuetext and the value shown (above the track, or floating over the thumb while it is touched). `ticks` draws the\n// graduations of the steps (and `marks` their words under the track); `tone` fills with the brand's gradient or its\n// accent alone.\nimport { Slider as SliderPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { tv } from \"../tv\";\n\nexport const slider = tv({\n slots: {\n root: \"flex flex-col gap-2 data-[orientation=vertical]:h-full data-[orientation=vertical]:items-center\",\n header: \"flex items-baseline justify-between gap-3 text-xs font-semibold text-fg-secondary\",\n value: \"font-mono text-[11px] tabular-nums text-fg-secondary\",\n control:\n \"relative flex touch-none select-none items-center data-disabled:cursor-not-allowed data-disabled:opacity-40 \" +\n \"data-[orientation=horizontal]:h-6 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-40 data-[orientation=vertical]:w-6 data-[orientation=vertical]:flex-col\",\n track:\n \"relative grow overflow-hidden rounded-full bg-surface-3 inset-shadow-well \" +\n \"data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5\",\n range: \"absolute rounded-full data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full\",\n thumb:\n \"group/thumb relative block h-5 w-5 cursor-grab rounded-full border-2 border-accent bg-fg-on-media shadow-raised transition-[box-shadow,scale] duration-150 \" +\n \"hover:ring-4 hover:ring-accent/15 focus-visible:outline-hidden focus-visible:focus-ring active:scale-110 active:cursor-grabbing motion-reduce:transition-none motion-reduce:active:scale-100\",\n // The value over the thumb: shown while the thumb is hovered, focused or held.\n bubble:\n \"pointer-events-none absolute bottom-full left-1/2 mb-2.5 -translate-x-1/2 whitespace-nowrap rounded-lg bg-fg px-2 py-1 font-mono text-[11px] font-semibold tabular-nums text-surface-0 opacity-0 shadow-floating \" +\n \"transition-opacity duration-150 after:absolute after:left-1/2 after:top-full after:-translate-x-1/2 after:border-4 after:border-transparent after:border-t-fg \" +\n \"group-hover/thumb:opacity-100 group-focus-visible/thumb:opacity-100 group-active/thumb:opacity-100 data-[always]:opacity-100 motion-reduce:transition-none\",\n bubbleVertical: \"bottom-auto left-full top-1/2 mb-0 ml-3 -translate-x-0 -translate-y-1/2 after:hidden\",\n ticks: \"pointer-events-none absolute inset-0\",\n tick: \"absolute rounded-full bg-border-strong data-[on]:bg-on-accent/70 data-[orientation=horizontal]:top-1/2 data-[orientation=horizontal]:h-1 data-[orientation=horizontal]:w-px data-[orientation=horizontal]:-translate-x-1/2 data-[orientation=horizontal]:-translate-y-1/2 data-[orientation=vertical]:left-1/2 data-[orientation=vertical]:h-px data-[orientation=vertical]:w-1 data-[orientation=vertical]:-translate-x-1/2 data-[orientation=vertical]:translate-y-1/2\",\n marks: \"relative h-4 w-full text-[11px] font-medium tabular-nums text-fg-secondary\",\n mark: \"absolute top-0 -translate-x-1/2 whitespace-nowrap first:translate-x-0 last:-translate-x-full\",\n },\n variants: {\n tone: {\n /** The brand's signature: accent → accent-2, a glow under it. */\n gradient: { range: \"bg-linear-to-r from-accent to-accent-2 shadow-glow data-[orientation=vertical]:bg-linear-to-t\" },\n /** The accent alone. */\n solid: { range: \"bg-accent\" },\n },\n size: {\n md: {},\n lg: {\n track: \"data-[orientation=horizontal]:h-2.5 data-[orientation=vertical]:w-2.5\",\n thumb: \"h-6 w-6\",\n control: \"data-[orientation=horizontal]:h-8 data-[orientation=vertical]:w-8\",\n },\n },\n },\n defaultVariants: { tone: \"gradient\", size: \"md\" },\n});\n\nexport type SliderValue = number | [number, number];\n\nexport type SliderMark = {\n /** Where the mark stands. */\n value: number;\n /** Its words under the track (\"0\", \"50 %\", \"Max\"), passed translated. */\n label: string;\n};\n\nexport type SliderProps<V extends SliderValue = number> = Omit<\n React.ComponentProps<typeof SliderPrimitive.Root>,\n \"value\" | \"defaultValue\" | \"onValueChange\" | \"onValueCommit\" | \"children\"\n> & {\n /** One number (a thumb) or two (a range). Controlled with `onValueChange`. */\n value?: V;\n /** The value at first, uncontrolled: one number, or two for a range. */\n defaultValue?: V;\n /** Called on every move, with one number or two. */\n onValueChange?: (value: V) => void;\n /** Called once the drag or the key press ends. */\n onValueCommit?: (value: V) => void;\n /** The accessible name — of the thumb, or of both thumbs of a range — passed translated. */\n label: string;\n /** For a range: each thumb's own name ([\"Minimum\", \"Maximum\"]), passed translated. */\n thumbLabels?: [string, string];\n /** The value as words (aria-valuetext) and as shown: \"1.5×\", \"−12 %\", \"3 min\". */\n formatValue?: (value: number) => string;\n /** Shows the label and the value above the track. Without it, `label` only names the thumb. */\n showLabel?: boolean;\n /** Shows the value floating over the thumb while it is hovered, focused or held (`\"always\"`: at all times). */\n floatingValue?: boolean | \"always\";\n /** Fills from this value instead of the minimum (a ±range from 0: brightness, balance). One horizontal thumb only. */\n origin?: number;\n /** Draws a graduation at every step (`true`, up to 40 of them) or at the values given. */\n ticks?: boolean | readonly number[];\n /** Words under the track at some values (`[{ value: 0, label: \"0\" }, { value: 100, label: \"100\" }]`). Horizontal only. */\n marks?: readonly SliderMark[];\n /**\n * `gradient` (the brand's accent → accent-2, a glow) or `solid` (the accent alone).\n * @default \"gradient\"\n */\n tone?: \"gradient\" | \"solid\";\n /**\n * md · lg (a thicker track and thumb: a hero control, a touch screen).\n * @default \"md\"\n */\n size?: \"md\" | \"lg\";\n};\n\nconst toArray = (v: SliderValue | undefined) => (v === undefined ? undefined : typeof v === \"number\" ? [v] : v);\n\n/** A slider on one value or a range: `value`/`defaultValue` + `onValueChange`, `min`, `max`, `step`, `orientation`. */\nexport function Slider<V extends SliderValue = number>({\n value,\n defaultValue,\n onValueChange,\n onValueCommit,\n label,\n thumbLabels,\n formatValue = String,\n showLabel,\n floatingValue,\n origin,\n ticks,\n marks,\n tone,\n size,\n min = 0,\n max = 100,\n step = 1,\n orientation = \"horizontal\",\n className,\n ...props\n}: SliderProps<V>) {\n const s = slider({ tone, size });\n const range = Array.isArray(value ?? defaultValue);\n const vertical = orientation === \"vertical\";\n const [inner, setInner] = React.useState(() => toArray(defaultValue) ?? [min]);\n const current = toArray(value) ?? inner;\n const out = (next: number[]) => (range ? next : next[0]) as V;\n const pct = (v: number) => ((v - min) / (max - min || 1)) * 100;\n const fill =\n origin !== undefined && !range && !vertical\n ? { left: `${Math.min(pct(origin), pct(current[0]!))}%`, right: `${100 - Math.max(pct(origin), pct(current[0]!))}%` }\n : undefined;\n const lo = range ? Math.min(...current) : (origin ?? min);\n const hi = range ? Math.max(...current) : current[0]!;\n const tickValues = ticks === true ? (max - min) / step <= 40 ? Array.from({ length: Math.round((max - min) / step) + 1 }, (_, i) => min + i * step) : [] : ticks ? [...ticks] : [];\n const id = React.useId();\n return (\n <div className={s.root({ className })} data-range={range ? \"\" : undefined} data-orientation={orientation}>\n {showLabel && (\n <div className={s.header()}>\n <span id={`${id}-label`}>{label}</span>\n <span className={s.value()} aria-hidden>\n {current.map(formatValue).join(\" – \")}\n </span>\n </div>\n )}\n <SliderPrimitive.Root\n min={min}\n max={max}\n step={step}\n orientation={orientation}\n value={current}\n onValueChange={(next) => {\n if (value === undefined) setInner(next);\n onValueChange?.(out(next));\n }}\n onValueCommit={onValueCommit && ((next) => onValueCommit(out(next)))}\n className={s.control()}\n {...props}\n >\n <SliderPrimitive.Track className={s.track()}>\n {fill ? <span data-origin=\"\" data-orientation={orientation} className={s.range()} style={fill} /> : <SliderPrimitive.Range className={s.range()} />}\n {tickValues.length ? (\n <span aria-hidden className={s.ticks()}>\n {tickValues.map((t) => (\n <span\n key={t}\n data-orientation={orientation}\n data-on={t > lo && t < hi ? \"\" : undefined}\n className={s.tick()}\n style={vertical ? { bottom: `${pct(t)}%` } : { left: `${pct(t)}%` }}\n />\n ))}\n </span>\n ) : null}\n </SliderPrimitive.Track>\n {current.map((v, i) => (\n <SliderPrimitive.Thumb\n key={i}\n aria-label={range ? (thumbLabels?.[i] ?? label) : showLabel ? undefined : label}\n aria-labelledby={!range && showLabel ? `${id}-label` : undefined}\n aria-valuetext={formatValue(v)}\n className={s.thumb()}\n >\n {floatingValue ? (\n <span aria-hidden data-always={floatingValue === \"always\" ? \"\" : undefined} className={s.bubble({ className: vertical ? s.bubbleVertical() : undefined })}>\n {formatValue(v)}\n </span>\n ) : null}\n </SliderPrimitive.Thumb>\n ))}\n </SliderPrimitive.Root>\n {marks?.length && !vertical ? (\n <div aria-hidden className={s.marks()}>\n {marks.map((m) => (\n <span key={m.value} className={s.mark()} style={{ left: `${pct(m.value)}%` }}>\n {m.label}\n </span>\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
package/dist/story.css CHANGED
@@ -61,7 +61,7 @@
61
61
  transition: border-color .2s ease, transform .25s var(--kz-ease), box-shadow .2s ease; }
62
62
  button.kzs-choice-item { cursor: pointer; width: 100%; }
63
63
  button.kzs-choice-item:disabled { cursor: not-allowed; opacity: .5; }
64
- .kzs-choice-item:is(:hover, :focus-visible):not(:disabled) { border-color: var(--kz-border-default); transform: translateY(-2px); }
64
+ .kzs-choice-item:is(:hover, :focus-visible):not(:disabled) { border-color: var(--kz-border-strong); }
65
65
  .kzs-choice-item:focus-visible { outline: 2px solid var(--kz-ring, var(--kz-accent)); outline-offset: 2px; }
66
66
  .kzs-choice-item[aria-checked="true"] { border-color: var(--kz-accent); box-shadow: 0 0 0 3px var(--kz-accent-soft); }
67
67
  .kzs-choice-top { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 8px; }
@@ -117,16 +117,11 @@ html.light .kzs-arcade .kzs-choice-item { background: radial-gradient(120% 70% a
117
117
  .kzs-arcade .kzs-choice-title { font-size: 13px; margin-bottom: 6px; }
118
118
  .kzs-arcade .kzs-choice-meta { font-family: var(--kz-font-mono); font-size: 10.5px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase;
119
119
  color: var(--kz-text-secondary); transition: color .25s ease; }
120
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible):not(:disabled), .kzs-arcade .kzs-choice-item[aria-checked="true"] { transform: translateY(-6px); border-color: var(--kz-accent);
121
- box-shadow: 0 34px 80px -30px var(--kz-accent), inset 0 0 0 1px color-mix(in srgb, var(--kz-accent) 50%, transparent); }
120
+ .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible):not(:disabled), .kzs-arcade .kzs-choice-item[aria-checked="true"] { border-color: var(--kz-accent);
121
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--kz-accent) 50%, transparent); }
122
122
  .kzs-arcade .kzs-choice-item:focus-visible { outline-offset: 4px; }
123
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-choice-aura { opacity: 1; transform: scale(1.15); }
124
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-choice-visual { transform: translateY(-4px) scale(1.06); }
123
+ .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-choice-aura { opacity: 1; }
125
124
  .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-corner { opacity: 1; }
126
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-corner[data-at="tl"] { transform: translate(4px, 4px); }
127
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-corner[data-at="tr"] { transform: translate(-4px, 4px); }
128
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-corner[data-at="bl"] { transform: translate(4px, -4px); }
129
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-corner[data-at="br"] { transform: translate(-4px, -4px); }
130
125
  .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-choice-meta { color: var(--kz-accent-text); }
131
126
  .kzs-arcade .kzs-choice-item[aria-checked="true"] .kzs-choice-check { display: none; }
132
127
 
@@ -145,7 +140,6 @@ html.light .kzs-arcade .kzs-choice-item { background: radial-gradient(120% 70% a
145
140
  .kzs-arcade .kzs-choice-frame { width: auto; height: 96px; }
146
141
  .kzs-arcade .kzs-choice-floor { width: 92px; margin-left: -46px; bottom: 6px; height: 18px; }
147
142
  .kzs-arcade .kzs-choice-visual { transform: scale(.78); }
148
- .kzs-arcade .kzs-choice-item:is(:hover, :focus-visible) .kzs-choice-visual { transform: scale(.82); }
149
143
  .kzs-arcade .kzs-choice-aura { top: 40px; left: 64px; width: 130px; margin-left: -65px; }
150
144
  }
151
145
 
@@ -179,7 +173,6 @@ html.light :is(.kzs-profile.kzs-arcade, .kzs-arcade .kzs-profile) { background:
179
173
  :is(.kzs-profile.kzs-arcade, .kzs-arcade .kzs-profile) .kzs-profile-aura { display: block; position: absolute; inset: -18px; border-radius: 50%;
180
174
  background: radial-gradient(circle, color-mix(in srgb, var(--kz-accent) 34%, transparent), transparent 70%); opacity: .5; filter: blur(10px); }
181
175
  :is(.kzs-profile.kzs-arcade, .kzs-arcade .kzs-profile) .kzs-profile-flash { display: block; position: absolute; inset: 0; border-radius: 50%; border: 2px solid var(--kz-accent); opacity: 0; pointer-events: none; }
182
- :is(.kzs-profile.kzs-arcade, .kzs-arcade .kzs-profile):hover .kzs-profile-visual { transform: scale(1.05); }
183
176
  :is(.kzs-profile.kzs-arcade, .kzs-arcade .kzs-profile) .kzs-profile-name { gap: 8px; font-family: var(--kz-font-mono); font-size: 11.5px; font-weight: 800; letter-spacing: .2em;
184
177
  text-transform: uppercase; color: var(--kz-accent-text); }
185
178
  :is(.kzs-profile.kzs-arcade, .kzs-arcade .kzs-profile) .kzs-profile-caption { font-family: var(--kz-font-mono); font-size: 12px; }
@@ -333,7 +326,7 @@ html.light :is(.kzs-promise.kzs-arcade, .kzs-arcade .kzs-promise) { background:
333
326
  :is(.kzs-achievement.kzs-arcade, .kzs-arcade .kzs-achievement) { padding: 18px 18px 20px; border-radius: 16px;
334
327
  background: color-mix(in srgb, var(--kz-surface-0) 82%, transparent); border: 1px solid color-mix(in srgb, var(--kz-accent) 22%, var(--kz-border-subtle)); }
335
328
  :is(.kzs-achievement.kzs-arcade, .kzs-arcade .kzs-achievement):hover { background: color-mix(in srgb, var(--kz-surface-0) 82%, transparent);
336
- border-color: color-mix(in srgb, var(--kz-accent) 55%, var(--kz-border-subtle)); transform: translateY(-2px); }
329
+ border-color: color-mix(in srgb, var(--kz-accent) 55%, var(--kz-border-subtle)); }
337
330
  :is(.kzs-achievement.kzs-arcade, .kzs-arcade .kzs-achievement) .kzs-achievement-eyebrow { font-family: var(--kz-font-mono); font-size: 11px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
338
331
  :is(.kzs-achievement.kzs-arcade, .kzs-arcade .kzs-achievement) .kzs-achievement-badge { font-family: var(--kz-font-mono); font-size: 9.5px; font-weight: 900; letter-spacing: .14em;
339
332
  text-transform: uppercase; padding: 2px 7px; border-radius: 4px; border: 1px solid color-mix(in srgb, var(--kz-accent-2, var(--kz-accent)) 45%, transparent); transform: rotate(-3deg); }
package/dist/theme.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { a as ButtonVariants } from './button-BmCrLCq7.js';
2
+ import { a as ButtonVariants } from './button-Cm9pFH3P.js';
3
3
  import 'tailwind-variants';
4
4
 
5
5
  type Mode = "dark" | "light" | "system";
package/dist/theme.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  buttonVariants
4
- } from "./chunk-CHOJUCVE.js";
4
+ } from "./chunk-SJS6RJIT.js";
5
5
  import "./chunk-D3T54RSL.js";
6
6
  import "./chunk-WEVYKZIF.js";
7
7
  import "./chunk-NSLXEDIS.js";
@@ -1,7 +1,7 @@
1
1
  import "./chunk-TDG7ED2W.js";
2
2
  import {
3
3
  Button
4
- } from "./chunk-6ZYRUOTA.js";
4
+ } from "./chunk-UV4HBVH7.js";
5
5
  import "./chunk-43PTCDTL.js";
6
6
  import "./chunk-2VNYHG4E.js";
7
7
  import "./chunk-W675RFOA.js";
@@ -31,7 +31,7 @@ function UpdatePrompt({ title, message, versionLabel, mark, updateLabel, onUpdat
31
31
  ] }),
32
32
  /* @__PURE__ */ jsxs("div", { className: s.actions(), children: [
33
33
  /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onLater, children: laterLabel }),
34
- /* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", shape: "cut", onClick: onUpdate, children: updateLabel })
34
+ /* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: onUpdate, children: updateLabel })
35
35
  ] })
36
36
  ] });
37
37
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/update-prompt/update-prompt.tsx"],"sourcesContent":["// Server-safe. The soft invitation to update: a dismissible banner, in the flow of the page, never a blocker.\n// Every word is a prop (the app passes them translated); the version and the store URL come from `useAppConfig`.\nimport { Button } from \"@krizaka/ui/button\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const updatePrompt = tv({\n slots: {\n root: \"flex w-full flex-wrap items-center gap-3 rounded-xl border border-border-default bg-surface-1 p-4 text-sm text-fg\",\n mark: \"flex h-10 w-10 shrink-0 items-center justify-center [&>svg]:h-10 [&>svg]:w-10\",\n content: \"flex min-w-0 flex-1 flex-col gap-0.5\",\n title: \"font-semibold text-fg\",\n message: \"text-fg-secondary\",\n version: \"font-mono text-xs text-fg-tertiary\",\n actions: \"flex shrink-0 items-center gap-2\",\n },\n});\n\nexport type UpdatePromptProps = Omit<React.ComponentProps<\"section\">, \"title\"> & {\n /** The headline (“A new version is available”). */\n title: React.ReactNode;\n /** Why update, in a sentence — the backend's localized `message`. */\n message?: React.ReactNode;\n /** The versions, in words and mono (“1.2.0 → 1.4.0”). */\n versionLabel?: React.ReactNode;\n /** The product's mark (decorative), e.g. `<OrazakaLogo />`. */\n mark?: React.ReactNode;\n /** The button that updates (“Update”). */\n updateLabel: string;\n /** Opens the store page, or reloads the app on the new version. */\n onUpdate: () => void;\n /** The way out (“Later”). */\n laterLabel: string;\n /** Called by the way out: the hook remembers it for this version. */\n onLater: () => void;\n};\n\n/** The soft update: an invitation that can be dismissed, announced politely. */\nexport function UpdatePrompt({ title, message, versionLabel, mark, updateLabel, onUpdate, laterLabel, onLater, className, ...props }: UpdatePromptProps) {\n const s = updatePrompt();\n return (\n <section role=\"region\" aria-label={typeof title === \"string\" ? title : undefined} data-kind=\"update-soft\" className={s.root({ className })} {...props}>\n {mark && (\n <div aria-hidden className={s.mark()}>\n {mark}\n </div>\n )}\n <div className={s.content()}>\n <p className={s.title()}>{title}</p>\n {message && <p className={s.message()}>{message}</p>}\n {versionLabel && <p className={s.version()}>{versionLabel}</p>}\n </div>\n <div className={s.actions()}>\n <Button variant=\"ghost\" size=\"sm\" onClick={onLater}>\n {laterLabel}\n </Button>\n <Button variant=\"primary\" size=\"sm\" shape=\"cut\" onClick={onUpdate}>\n {updateLabel}\n </Button>\n </div>\n </section>\n );\n}\n"],"mappings":";;;;;;;;;AAIA,SAAS,UAAU;AAuCX,cAIF,YAJE;AArCD,IAAM,eAAe,GAAG;AAAA,EAC7B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACF,CAAC;AAsBM,SAAS,aAAa,EAAE,OAAO,SAAS,cAAc,MAAM,aAAa,UAAU,YAAY,SAAS,WAAW,GAAG,MAAM,GAAsB;AACvJ,QAAM,IAAI,aAAa;AACvB,SACE,qBAAC,aAAQ,MAAK,UAAS,cAAY,OAAO,UAAU,WAAW,QAAQ,QAAW,aAAU,eAAc,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC7I;AAAA,YACC,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,KAAK,GAChC,gBACH;AAAA,IAEF,qBAAC,SAAI,WAAW,EAAE,QAAQ,GACxB;AAAA,0BAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,MAC/B,WAAW,oBAAC,OAAE,WAAW,EAAE,QAAQ,GAAI,mBAAQ;AAAA,MAC/C,gBAAgB,oBAAC,OAAE,WAAW,EAAE,QAAQ,GAAI,wBAAa;AAAA,OAC5D;AAAA,IACA,qBAAC,SAAI,WAAW,EAAE,QAAQ,GACxB;AAAA,0BAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,SACxC,sBACH;AAAA,MACA,oBAAC,UAAO,SAAQ,WAAU,MAAK,MAAK,OAAM,OAAM,SAAS,UACtD,uBACH;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/update-prompt/update-prompt.tsx"],"sourcesContent":["// Server-safe. The soft invitation to update: a dismissible banner, in the flow of the page, never a blocker.\n// Every word is a prop (the app passes them translated); the version and the store URL come from `useAppConfig`.\nimport { Button } from \"@krizaka/ui/button\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const updatePrompt = tv({\n slots: {\n root: \"flex w-full flex-wrap items-center gap-3 rounded-xl border border-border-default bg-surface-1 p-4 text-sm text-fg\",\n mark: \"flex h-10 w-10 shrink-0 items-center justify-center [&>svg]:h-10 [&>svg]:w-10\",\n content: \"flex min-w-0 flex-1 flex-col gap-0.5\",\n title: \"font-semibold text-fg\",\n message: \"text-fg-secondary\",\n version: \"font-mono text-xs text-fg-tertiary\",\n actions: \"flex shrink-0 items-center gap-2\",\n },\n});\n\nexport type UpdatePromptProps = Omit<React.ComponentProps<\"section\">, \"title\"> & {\n /** The headline (“A new version is available”). */\n title: React.ReactNode;\n /** Why update, in a sentence — the backend's localized `message`. */\n message?: React.ReactNode;\n /** The versions, in words and mono (“1.2.0 → 1.4.0”). */\n versionLabel?: React.ReactNode;\n /** The product's mark (decorative), e.g. `<OrazakaLogo />`. */\n mark?: React.ReactNode;\n /** The button that updates (“Update”). */\n updateLabel: string;\n /** Opens the store page, or reloads the app on the new version. */\n onUpdate: () => void;\n /** The way out (“Later”). */\n laterLabel: string;\n /** Called by the way out: the hook remembers it for this version. */\n onLater: () => void;\n};\n\n/** The soft update: an invitation that can be dismissed, announced politely. */\nexport function UpdatePrompt({ title, message, versionLabel, mark, updateLabel, onUpdate, laterLabel, onLater, className, ...props }: UpdatePromptProps) {\n const s = updatePrompt();\n return (\n <section role=\"region\" aria-label={typeof title === \"string\" ? title : undefined} data-kind=\"update-soft\" className={s.root({ className })} {...props}>\n {mark && (\n <div aria-hidden className={s.mark()}>\n {mark}\n </div>\n )}\n <div className={s.content()}>\n <p className={s.title()}>{title}</p>\n {message && <p className={s.message()}>{message}</p>}\n {versionLabel && <p className={s.version()}>{versionLabel}</p>}\n </div>\n <div className={s.actions()}>\n <Button variant=\"ghost\" size=\"sm\" onClick={onLater}>\n {laterLabel}\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={onUpdate}>\n {updateLabel}\n </Button>\n </div>\n </section>\n );\n}\n"],"mappings":";;;;;;;;;AAIA,SAAS,UAAU;AAuCX,cAIF,YAJE;AArCD,IAAM,eAAe,GAAG;AAAA,EAC7B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACF,CAAC;AAsBM,SAAS,aAAa,EAAE,OAAO,SAAS,cAAc,MAAM,aAAa,UAAU,YAAY,SAAS,WAAW,GAAG,MAAM,GAAsB;AACvJ,QAAM,IAAI,aAAa;AACvB,SACE,qBAAC,aAAQ,MAAK,UAAS,cAAY,OAAO,UAAU,WAAW,QAAQ,QAAW,aAAU,eAAc,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC7I;AAAA,YACC,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,KAAK,GAChC,gBACH;AAAA,IAEF,qBAAC,SAAI,WAAW,EAAE,QAAQ,GACxB;AAAA,0BAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,MAC/B,WAAW,oBAAC,OAAE,WAAW,EAAE,QAAQ,GAAI,mBAAQ;AAAA,MAC/C,gBAAgB,oBAAC,OAAE,WAAW,EAAE,QAAQ,GAAI,wBAAa;AAAA,OAC5D;AAAA,IACA,qBAAC,SAAI,WAAW,EAAE,QAAQ,GACxB;AAAA,0BAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,SACxC,sBACH;AAAA,MACA,oBAAC,UAAO,SAAQ,WAAU,MAAK,MAAK,SAAS,UAC1C,uBACH;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-KB7OLYIJ.js";
5
5
  import {
6
6
  IconButton
7
- } from "./chunk-DZU6RMYD.js";
7
+ } from "./chunk-3DHNN5V7.js";
8
8
  import "./chunk-D3T54RSL.js";
9
9
  import {
10
10
  cn
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Slider
4
- } from "./chunk-KM6VAKIE.js";
4
+ } from "./chunk-RE5WJ4QP.js";
5
5
  import "./chunk-HJFRHYCI.js";
6
6
  import "./chunk-NSLXEDIS.js";
7
7
  import {
@@ -30,7 +30,7 @@ var videoPlayer = tv({
30
30
  root: "theme-dark group/player relative isolate w-full overflow-hidden rounded-xl bg-media text-fg-on-media focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring data-[idle]:cursor-none",
31
31
  video: "absolute inset-0 h-full w-full object-contain",
32
32
  poster: "pointer-events-none absolute inset-0 h-full w-full object-contain",
33
- big: "absolute left-1/2 top-1/2 z-10 inline-flex h-16 w-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-scrim-strong text-fg-on-media shadow-lg backdrop-blur-sm transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
33
+ big: "absolute left-1/2 top-1/2 z-10 inline-flex h-16 w-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-scrim-strong text-fg-on-media shadow-lg backdrop-blur-sm transition-colors hover:bg-scrim motion-reduce:transition-none focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
34
34
  bar: "absolute inset-x-0 bottom-0 z-20 flex flex-col gap-1 bg-linear-to-t from-scrim-strong via-scrim to-transparent px-3 pb-2 pt-10 transition-opacity duration-300 motion-reduce:transition-none group-data-[idle]/player:opacity-0 group-focus-within/player:opacity-100",
35
35
  row: "flex items-center gap-1",
36
36
  button: "inline-flex h-9 min-w-9 shrink-0 items-center justify-center gap-1 rounded-md px-1.5 text-xs font-semibold text-fg-on-media transition-colors hover:bg-fg-on-media/15 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-pressed:bg-fg-on-media/20",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/video-player/video-player.tsx"],"sourcesContent":["// Client. A `<video>` with its own controls, accessible from end to end: a named region the keyboard reaches (Space /\n// K, arrows, J / L, M, F, C, Home / End, 0–9), every button named by a prop, the seek and volume sliders of\n// `@krizaka/ui/slider` with the time read aloud. HLS plays natively where the browser can (Safari, iOS) and through\n// hls.js elsewhere — loaded only then, by the app's `loadHls` (`() => import(\"hls.js\")`): an optional peer, never in\n// the bundle of a page that does not play HLS. A signed address can be resolved at the last moment (`src` as a\n// function), again after an error; the video pauses when it leaves the screen; autoplay waits under reduced motion.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CaptionsGlyph, FullscreenGlyph, PauseGlyph, PipGlyph, PlayGlyph, RetryGlyph, VolumeGlyph } from \"../glyphs\";\nimport { clamp, formatClock, playSafely, useInView, usePrefersReducedMotion } from \"../media\";\nimport { Slider } from \"../slider\";\n\nexport const videoPlayer = tv({\n slots: {\n root:\n \"theme-dark group/player relative isolate w-full overflow-hidden rounded-xl bg-media text-fg-on-media \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring data-[idle]:cursor-none\",\n video: \"absolute inset-0 h-full w-full object-contain\",\n poster: \"pointer-events-none absolute inset-0 h-full w-full object-contain\",\n big:\n \"absolute left-1/2 top-1/2 z-10 inline-flex h-16 w-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full \" +\n \"bg-scrim-strong text-fg-on-media shadow-lg backdrop-blur-sm transition-transform hover:scale-105 motion-reduce:transition-none motion-reduce:hover:scale-100 \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n bar:\n \"absolute inset-x-0 bottom-0 z-20 flex flex-col gap-1 bg-linear-to-t from-scrim-strong via-scrim to-transparent px-3 pb-2 pt-10 \" +\n \"transition-opacity duration-300 motion-reduce:transition-none group-data-[idle]/player:opacity-0 group-focus-within/player:opacity-100\",\n row: \"flex items-center gap-1\",\n button:\n \"inline-flex h-9 min-w-9 shrink-0 items-center justify-center gap-1 rounded-md px-1.5 text-xs font-semibold text-fg-on-media \" +\n \"transition-colors hover:bg-fg-on-media/15 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-pressed:bg-fg-on-media/20\",\n time: \"px-1.5 font-mono text-[11px] tabular-nums text-fg-on-media\",\n volume: \"hidden w-20 items-center sm:flex\",\n status: \"absolute inset-0 z-30 flex flex-col items-center justify-center gap-3 bg-scrim-strong p-6 text-center text-sm\",\n spinner: \"h-10 w-10 animate-spin rounded-full border-2 border-fg-on-media/30 border-t-fg-on-media motion-reduce:animate-none\",\n overlay: \"absolute inset-0 z-30\",\n },\n});\n\n/** What `loadHls` resolves to: the module of hls.js (only the members the player uses are typed). */\nexport type HlsModule = {\n default: {\n new (config?: Record<string, unknown>): {\n loadSource(url: string): void;\n attachMedia(media: HTMLMediaElement): void;\n destroy(): void;\n startLoad(): void;\n recoverMediaError(): void;\n on(event: string, listener: (event: string, data: { fatal?: boolean; type?: string }) => void): void;\n };\n isSupported(): boolean;\n Events: { ERROR: string };\n ErrorTypes: { NETWORK_ERROR: string; MEDIA_ERROR: string };\n };\n};\n\nexport type VideoTrack = {\n /** The WebVTT file. */\n src: string;\n /** Its language, BCP 47 (`\"fr\"`). */\n srcLang: string;\n /** Its name in the menu (\"Français\"), passed translated. */\n label: string;\n /** `subtitles` (default) or `captions` (with the sounds, for deaf viewers). */\n kind?: \"subtitles\" | \"captions\";\n /** Shown from the start. */\n default?: boolean;\n};\n\nexport type VideoPlayerLabels = {\n play: string;\n pause: string;\n mute: string;\n unmute: string;\n volume: string;\n seek: string;\n /** The speed button: `(rate) => \"Speed \" + rate + \"×\"`. */\n speed: (rate: number) => string;\n /** The captions button: `(track) => \"Subtitles: \" + (track ?? \"off\")`, the track's label or `null` when off. */\n captions: (track: string | null) => string;\n fullscreen: string;\n exitFullscreen: string;\n pictureInPicture: string;\n /** Read while the video waits for data. */\n loading: string;\n /** The video cannot play. */\n error: string;\n /** Tries again (resolves a signed `src` again). */\n retry: string;\n /** The seek slider's value: `(time, duration) => \"1:05 of 3:20\"`. */\n time: (time: string, duration: string) => string;\n};\n\nexport const videoPlayerLabels: VideoPlayerLabels = {\n play: \"Play\",\n pause: \"Pause\",\n mute: \"Mute\",\n unmute: \"Unmute\",\n volume: \"Volume\",\n seek: \"Seek\",\n speed: (rate) => `Speed ${rate}×`,\n captions: (track) => `Subtitles: ${track ?? \"off\"}`,\n fullscreen: \"Full screen\",\n exitFullscreen: \"Exit full screen\",\n pictureInPicture: \"Picture in picture\",\n loading: \"Loading\",\n error: \"This video cannot be played.\",\n retry: \"Try again\",\n time: (time, duration) => `${time} of ${duration}`,\n};\n\nexport type VideoPlayerProps = {\n /** The address of the video (MP4, WebM, or an HLS `.m3u8`), or a function that resolves a signed one when needed. */\n src: string | (() => Promise<string>);\n /** `auto` (default): HLS when the address ends in `.m3u8`. */\n type?: \"auto\" | \"hls\" | \"file\";\n /** Loads hls.js when the browser cannot play HLS itself: `() => import(\"hls.js\")`. Without it, HLS needs Safari. */\n loadHls?: () => Promise<HlsModule>;\n /** The accessible name of the player (\"Video: Sunset over Montréal\"), passed translated. */\n title: string;\n /** The picture shown before playback. */\n poster?: string;\n /** Starts playing, muted (browsers refuse sound without a gesture), once on screen and again each time it comes back — not under reduced motion. */\n autoPlay?: boolean;\n /** Starts muted. */\n muted?: boolean;\n /** Plays again from the start at the end. */\n loop?: boolean;\n /** How much to fetch before playback: `none` (a list of many videos), `metadata` (default), `auto`. */\n preload?: \"none\" | \"metadata\" | \"auto\";\n /** Subtitles or captions (WebVTT): the C key and a button cycle through them. */\n tracks?: readonly VideoTrack[];\n /** The speeds offered by the speed button. Default `[0.5, 1, 1.25, 1.5, 2]`. */\n playbackRates?: readonly number[];\n /** Pauses when less than a quarter of the player is on screen. Default `true`. */\n pauseWhenHidden?: boolean;\n /** Shows the controls (default). `false`: a bare video (a background loop) — give it no sound. */\n controls?: boolean;\n /** Covers the video and hides the controls: a gate (sign in, unlock, age check) drawn by the app. */\n overlay?: React.ReactNode;\n /** The width / height ratio of the frame. Default `\"16 / 9\"`; `\"9 / 16\"` for a vertical video. */\n aspectRatio?: string;\n /** Called when playback starts. */\n onPlay?: () => void;\n /** Called when playback pauses. */\n onPause?: () => void;\n /** Called at the end. */\n onEnded?: () => void;\n /** Called as the time moves, in seconds (a few times a second). */\n onTimeUpdate?: (time: number) => void;\n /** Called when the video cannot play (a network failure, an expired address). */\n onError?: (error: unknown) => void;\n /** The words, passed translated; English by default. */\n labels?: Partial<VideoPlayerLabels>;\n /** Classes merged on the root. */\n className?: string;\n};\n\nconst RATES = [0.5, 1, 1.25, 1.5, 2] as const;\nconst isHls = (url: string, type: VideoPlayerProps[\"type\"]) => type === \"hls\" || (type !== \"file\" && /\\.m3u8(\\?|#|$)/i.test(url));\n\n/** Shows the text track `index` of a video (and hides the others); -1 hides them all. */\nfunction showTrack(element: HTMLVideoElement, index: number) {\n const list = element.textTracks;\n for (let i = 0; i < list.length; i += 1) list[i]!.mode = i === index ? \"showing\" : \"disabled\";\n}\n\n/** A video player with accessible controls, HLS on demand, signed sources, subtitles, speed, full screen. */\nexport function VideoPlayer({\n src,\n type = \"auto\",\n loadHls,\n title,\n poster,\n autoPlay,\n muted: initiallyMuted = false,\n loop,\n preload = \"metadata\",\n tracks = [],\n playbackRates = RATES,\n pauseWhenHidden = true,\n controls = true,\n overlay,\n aspectRatio = \"16 / 9\",\n onPlay,\n onPause,\n onEnded,\n onTimeUpdate,\n onError,\n labels: given,\n className,\n}: VideoPlayerProps) {\n const labels = { ...videoPlayerLabels, ...given };\n const s = videoPlayer();\n const root = React.useRef<HTMLDivElement>(null);\n const video = React.useRef<HTMLVideoElement>(null);\n const reduce = usePrefersReducedMotion();\n const [resolved, setResolved] = React.useState<{ attempt: number; url: string } | null>(null);\n const [attempt, setAttempt] = React.useState(0);\n const [wanted, setWanted] = React.useState(false);\n const [playing, setPlaying] = React.useState(false);\n const [time, setTime] = React.useState(0);\n const [duration, setDuration] = React.useState(0);\n const [volume, setVolume] = React.useState(1);\n const [muted, setMuted] = React.useState(initiallyMuted || Boolean(autoPlay));\n const [rate, setRate] = React.useState(1);\n const [caption, setCaption] = React.useState(() => tracks.findIndex((t) => t.default));\n const [fullscreen, setFullscreen] = React.useState(false);\n const [waiting, setWaiting] = React.useState(false);\n const [failed, setFailed] = React.useState(false);\n const [idle, setIdle] = React.useState(false);\n // The poster is an image over the video until the first play: it loads like any image (lazy, decoded once), the\n // same in every browser — the `poster` attribute is painted late and differently.\n const [started, setStarted] = React.useState(false);\n const idleTimer = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const url = typeof src === \"string\" ? src : resolved?.attempt === attempt ? resolved.url : null;\n const needSource = typeof src === \"function\" && (preload !== \"none\" || wanted || (autoPlay && !reduce));\n\n // A signed source is resolved when it is needed, and again on \"Try again\".\n React.useEffect(() => {\n if (typeof src !== \"function\" || !needSource) return;\n let live = true;\n src().then(\n (next) => live && setResolved({ attempt, url: next }),\n (error: unknown) => {\n if (!live) return;\n setFailed(true);\n onError?.(error);\n },\n );\n return () => {\n live = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `onError` is a callback, not a reason to resolve again\n }, [src, needSource, attempt]);\n\n // Attaches the source: natively, or through hls.js when the browser needs it.\n React.useEffect(() => {\n const element = video.current;\n if (!element || !url) return;\n let hls: InstanceType<HlsModule[\"default\"]> | null = null;\n let live = true;\n const fail = (error: unknown) => {\n if (!live) return;\n setFailed(true);\n onError?.(error);\n };\n if (isHls(url, type) && !element.canPlayType(\"application/vnd.apple.mpegurl\")) {\n if (!loadHls) fail(new Error(\"VideoPlayer: HLS needs `loadHls` in this browser.\"));\n else\n loadHls().then(({ default: Hls }) => {\n if (!live) return;\n if (!Hls.isSupported()) return fail(new Error(\"VideoPlayer: HLS is not supported here.\"));\n hls = new Hls({ enableWorker: true, backBufferLength: 60 });\n hls.on(Hls.Events.ERROR, (_event, data) => {\n if (!data.fatal) return;\n if (data.type === Hls.ErrorTypes.NETWORK_ERROR) hls?.startLoad();\n else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) hls?.recoverMediaError();\n else fail(data);\n });\n hls.loadSource(url);\n hls.attachMedia(element);\n }, fail);\n } else element.src = url;\n return () => {\n live = false;\n hls?.destroy();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `onError` and `loadHls` are callbacks\n }, [url, type]);\n\n // An autoplay waits for the player to be on screen (nothing is fetched before, with `preload=\"none\"`), and plays\n // again each time it comes back: a page of loops costs only the ones in view.\n const [inView, setInView] = React.useState(() => !pauseWhenHidden || typeof IntersectionObserver === \"undefined\");\n\n // Plays once the source is there, when it was asked for (a click before a signed source resolved).\n React.useEffect(() => {\n const element = video.current;\n if (!element || !url || !wanted) return;\n playSafely(element);\n }, [url, wanted]);\n\n // An autoplay: while in view, never under reduced motion.\n React.useEffect(() => {\n const element = video.current;\n if (!element || !url || !autoPlay || reduce || !inView) return;\n playSafely(element);\n }, [url, autoPlay, reduce, inView]);\n\n React.useEffect(() => {\n if (video.current) showTrack(video.current, caption);\n }, [caption, tracks.length]);\n\n React.useEffect(() => {\n const change = () => setFullscreen(document.fullscreenElement === root.current);\n document.addEventListener(\"fullscreenchange\", change);\n return () => document.removeEventListener(\"fullscreenchange\", change);\n }, []);\n React.useEffect(() => () => clearTimeout(idleTimer.current), []);\n\n useInView(\n root,\n (visible) => {\n setInView(visible);\n if (!visible && video.current && !video.current.paused) video.current.pause();\n },\n pauseWhenHidden,\n );\n\n const play = () => {\n setWanted(true);\n setFailed(false);\n playSafely(video.current);\n };\n const toggle = () => (playing ? video.current?.pause() : play());\n const seek = (to: number) => {\n if (!video.current) return;\n video.current.currentTime = clamp(to, 0, duration || video.current.duration || 0);\n setTime(video.current.currentTime);\n };\n const changeVolume = (to: number) => {\n if (!video.current) return;\n const next = clamp(to, 0, 1);\n video.current.volume = next;\n video.current.muted = next === 0;\n setVolume(next);\n setMuted(next === 0);\n };\n const toggleMute = () => {\n if (!video.current) return;\n if (muted && volume === 0) changeVolume(0.5);\n video.current.muted = !muted;\n setMuted(!muted);\n };\n const cycleRate = () => {\n const next = playbackRates[(playbackRates.indexOf(rate) + 1) % playbackRates.length] ?? 1;\n if (video.current) video.current.playbackRate = next;\n setRate(next);\n };\n const cycleCaption = () => tracks.length > 0 && setCaption((c) => (c + 2) % (tracks.length + 1) - 1);\n const toggleFullscreen = () => {\n const element = root.current;\n if (!element) return;\n if (document.fullscreenElement) void document.exitFullscreen();\n else if (element.requestFullscreen) void element.requestFullscreen();\n else (video.current as HTMLVideoElement & { webkitEnterFullscreen?: () => void })?.webkitEnterFullscreen?.();\n };\n const pip = () => {\n if (document.pictureInPictureElement) void document.exitPictureInPicture();\n else void video.current?.requestPictureInPicture?.();\n };\n const wake = () => {\n setIdle(false);\n clearTimeout(idleTimer.current);\n if (playing) idleTimer.current = setTimeout(() => setIdle(true), 2500);\n };\n\n const onKeyDown = (event: React.KeyboardEvent) => {\n const target = event.target as HTMLElement;\n const inControl = target.getAttribute(\"role\") === \"slider\";\n const key = event.key.length === 1 ? event.key.toLowerCase() : event.key;\n const now = video.current?.currentTime ?? 0;\n const actions: Record<string, (() => void) | undefined> = {\n \" \": target.tagName === \"BUTTON\" ? undefined : toggle,\n k: toggle,\n j: () => seek(now - 10),\n l: () => seek(now + 10),\n m: toggleMute,\n f: toggleFullscreen,\n c: tracks.length ? cycleCaption : undefined,\n ArrowLeft: inControl ? undefined : () => seek(now - 5),\n ArrowRight: inControl ? undefined : () => seek(now + 5),\n ArrowUp: inControl ? undefined : () => changeVolume(volume + 0.1),\n ArrowDown: inControl ? undefined : () => changeVolume(volume - 0.1),\n Home: inControl ? undefined : () => seek(0),\n End: inControl ? undefined : () => seek(duration),\n };\n const action = /^[0-9]$/.test(key) && !inControl ? () => seek((Number(key) / 10) * duration) : actions[key];\n if (!action || event.metaKey || event.ctrlKey || event.altKey) return;\n event.preventDefault();\n action();\n wake();\n };\n\n const showControls = controls && !overlay;\n const pipSupported = typeof document !== \"undefined\" && \"pictureInPictureEnabled\" in document && document.pictureInPictureEnabled;\n\n return (\n <div\n ref={root}\n role=\"region\"\n aria-label={title}\n tabIndex={showControls ? 0 : undefined}\n data-idle={idle && playing ? \"\" : undefined}\n data-state={playing ? \"playing\" : \"paused\"}\n className={s.root({ className })}\n style={{ aspectRatio }}\n onKeyDown={showControls ? onKeyDown : undefined}\n onPointerMove={showControls ? wake : undefined}\n onPointerLeave={() => playing && setIdle(true)}\n >\n <video\n ref={video}\n className={s.video()}\n preload={preload}\n loop={loop}\n muted={muted}\n playsInline\n crossOrigin={tracks.length ? \"anonymous\" : undefined}\n onClick={showControls ? toggle : undefined}\n onPlay={() => {\n setStarted(true);\n setPlaying(true);\n wake();\n onPlay?.();\n }}\n onPause={() => {\n setPlaying(false);\n setIdle(false);\n onPause?.();\n }}\n onEnded={() => onEnded?.()}\n onTimeUpdate={(event) => {\n setTime(event.currentTarget.currentTime);\n onTimeUpdate?.(event.currentTarget.currentTime);\n }}\n onDurationChange={(event) => setDuration(Number.isFinite(event.currentTarget.duration) ? event.currentTarget.duration : 0)}\n onWaiting={() => setWaiting(true)}\n onPlaying={() => setWaiting(false)}\n onCanPlay={() => setWaiting(false)}\n onError={(event) => {\n setFailed(true);\n onError?.(event.currentTarget.error);\n }}\n >\n {tracks.map((track) => (\n <track key={track.src} src={track.src} srcLang={track.srcLang} label={track.label} kind={track.kind ?? \"subtitles\"} default={track.default} />\n ))}\n </video>\n\n {poster && !started ? <img src={poster} alt=\"\" aria-hidden decoding=\"async\" className={s.poster()} /> : null}\n\n {showControls && !playing && !failed && !waiting && (\n <button type=\"button\" className={s.big()} aria-label={labels.play} onClick={play}>\n <PlayGlyph className=\"ml-1 h-7 w-7\" />\n </button>\n )}\n\n {waiting && !failed && (\n <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center\">\n <span className={s.spinner()} aria-hidden />\n <span role=\"status\" className=\"sr-only\">\n {labels.loading}\n </span>\n </div>\n )}\n\n {failed && (\n <div role=\"alert\" className={s.status()}>\n <p>{labels.error}</p>\n <button\n type=\"button\"\n className={s.button({ className: \"border border-fg-on-media/40 px-3\" })}\n onClick={() => {\n setFailed(false);\n setAttempt((a) => a + 1);\n video.current?.load();\n }}\n >\n <RetryGlyph className=\"h-4 w-4\" />\n {labels.retry}\n </button>\n </div>\n )}\n\n {overlay ? <div className={s.overlay()}>{overlay}</div> : null}\n\n {showControls && (\n <div className={s.bar()}>\n <Slider\n label={labels.seek}\n min={0}\n max={duration || 1}\n step={0.1}\n value={Math.min(time, duration || 1)}\n onValueChange={seek}\n formatValue={(v) => labels.time(formatClock(v), formatClock(duration))}\n disabled={!duration}\n className=\"[&_[role=slider]]:h-4 [&_[role=slider]]:w-4\"\n />\n <div className={s.row()}>\n <button type=\"button\" className={s.button()} aria-label={playing ? labels.pause : labels.play} onClick={toggle}>\n {playing ? <PauseGlyph className=\"h-5 w-5\" /> : <PlayGlyph className=\"h-5 w-5\" />}\n </button>\n <button type=\"button\" className={s.button()} aria-label={muted ? labels.unmute : labels.mute} onClick={toggleMute}>\n <VolumeGlyph muted={muted} className=\"h-5 w-5\" />\n </button>\n <div className={s.volume()}>\n <Slider label={labels.volume} min={0} max={1} step={0.05} value={muted ? 0 : volume} onValueChange={changeVolume} formatValue={(v) => `${Math.round(v * 100)} %`} className=\"w-full\" />\n </div>\n <span className={s.time()} aria-hidden>\n {formatClock(time)} / {formatClock(duration)}\n </span>\n <span className=\"flex-1\" />\n {playbackRates.length > 1 && (\n <button type=\"button\" className={s.button()} aria-label={labels.speed(rate)} onClick={cycleRate}>\n {rate}×\n </button>\n )}\n {tracks.length > 0 && (\n <button type=\"button\" className={s.button()} aria-pressed={caption >= 0} aria-label={labels.captions(caption >= 0 ? (tracks[caption]?.label ?? null) : null)} onClick={cycleCaption}>\n <CaptionsGlyph className=\"h-5 w-5\" />\n </button>\n )}\n {pipSupported && (\n <button type=\"button\" className={s.button()} aria-label={labels.pictureInPicture} onClick={pip}>\n <PipGlyph className=\"h-5 w-5\" />\n </button>\n )}\n <button type=\"button\" className={s.button()} aria-label={fullscreen ? labels.exitFullscreen : labels.fullscreen} onClick={toggleFullscreen}>\n <FullscreenGlyph exit={fullscreen} className=\"h-5 w-5\" />\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAMA,YAAY,WAAW;AACvB,SAAS,UAAU;AA8aT,cAaF,YAbE;AAxaH,IAAM,cAAc,GAAG;AAAA,EAC5B,OAAO;AAAA,IACL,MACE;AAAA,IAEF,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KACE;AAAA,IAGF,KACE;AAAA,IAEF,KAAK;AAAA,IACL,QACE;AAAA,IAEF,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACF,CAAC;AAwDM,IAAM,oBAAuC;AAAA,EAClD,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO,CAAC,SAAS,SAAS,IAAI;AAAA,EAC9B,UAAU,CAAC,UAAU,cAAc,SAAS,KAAK;AAAA,EACjD,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,QAAQ;AAClD;AAiDA,IAAM,QAAQ,CAAC,KAAK,GAAG,MAAM,KAAK,CAAC;AACnC,IAAM,QAAQ,CAAC,KAAa,SAAmC,SAAS,SAAU,SAAS,UAAU,kBAAkB,KAAK,GAAG;AAG/H,SAAS,UAAU,SAA2B,OAAe;AAC3D,QAAM,OAAO,QAAQ;AACrB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,EAAG,MAAK,CAAC,EAAG,OAAO,MAAM,QAAQ,YAAY;AACrF;AAGO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO,iBAAiB;AAAA,EACxB;AAAA,EACA,UAAU;AAAA,EACV,SAAS,CAAC;AAAA,EACV,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AACF,GAAqB;AACnB,QAAM,SAAS,EAAE,GAAG,mBAAmB,GAAG,MAAM;AAChD,QAAM,IAAI,YAAY;AACtB,QAAM,OAAa,aAAuB,IAAI;AAC9C,QAAM,QAAc,aAAyB,IAAI;AACjD,QAAM,SAAS,wBAAwB;AACvC,QAAM,CAAC,UAAU,WAAW,IAAU,eAAkD,IAAI;AAC5F,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,CAAC;AAC9C,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,KAAK;AAChD,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,KAAK;AAClD,QAAM,CAAC,MAAM,OAAO,IAAU,eAAS,CAAC;AACxC,QAAM,CAAC,UAAU,WAAW,IAAU,eAAS,CAAC;AAChD,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,CAAC;AAC5C,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAS,kBAAkB,QAAQ,QAAQ,CAAC;AAC5E,QAAM,CAAC,MAAM,OAAO,IAAU,eAAS,CAAC;AACxC,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC;AACrF,QAAM,CAAC,YAAY,aAAa,IAAU,eAAS,KAAK;AACxD,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,KAAK;AAClD,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,KAAK;AAChD,QAAM,CAAC,MAAM,OAAO,IAAU,eAAS,KAAK;AAG5C,QAAM,CAAC,SAAS,UAAU,IAAU,eAAS,KAAK;AAClD,QAAM,YAAkB,aAAkD,MAAS;AAEnF,QAAM,MAAM,OAAO,QAAQ,WAAW,MAAM,UAAU,YAAY,UAAU,SAAS,MAAM;AAC3F,QAAM,aAAa,OAAO,QAAQ,eAAe,YAAY,UAAU,UAAW,YAAY,CAAC;AAG/F,EAAM,gBAAU,MAAM;AACpB,QAAI,OAAO,QAAQ,cAAc,CAAC,WAAY;AAC9C,QAAI,OAAO;AACX,QAAI,EAAE;AAAA,MACJ,CAAC,SAAS,QAAQ,YAAY,EAAE,SAAS,KAAK,KAAK,CAAC;AAAA,MACpD,CAAC,UAAmB;AAClB,YAAI,CAAC,KAAM;AACX,kBAAU,IAAI;AACd,kBAAU,KAAK;AAAA,MACjB;AAAA,IACF;AACA,WAAO,MAAM;AACX,aAAO;AAAA,IACT;AAAA,EAEF,GAAG,CAAC,KAAK,YAAY,OAAO,CAAC;AAG7B,EAAM,gBAAU,MAAM;AACpB,UAAM,UAAU,MAAM;AACtB,QAAI,CAAC,WAAW,CAAC,IAAK;AACtB,QAAI,MAAiD;AACrD,QAAI,OAAO;AACX,UAAM,OAAO,CAAC,UAAmB;AAC/B,UAAI,CAAC,KAAM;AACX,gBAAU,IAAI;AACd,gBAAU,KAAK;AAAA,IACjB;AACA,QAAI,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,YAAY,+BAA+B,GAAG;AAC7E,UAAI,CAAC,QAAS,MAAK,IAAI,MAAM,mDAAmD,CAAC;AAAA;AAE/E,gBAAQ,EAAE,KAAK,CAAC,EAAE,SAAS,IAAI,MAAM;AACnC,cAAI,CAAC,KAAM;AACX,cAAI,CAAC,IAAI,YAAY,EAAG,QAAO,KAAK,IAAI,MAAM,yCAAyC,CAAC;AACxF,gBAAM,IAAI,IAAI,EAAE,cAAc,MAAM,kBAAkB,GAAG,CAAC;AAC1D,cAAI,GAAG,IAAI,OAAO,OAAO,CAAC,QAAQ,SAAS;AACzC,gBAAI,CAAC,KAAK,MAAO;AACjB,gBAAI,KAAK,SAAS,IAAI,WAAW,cAAe,MAAK,UAAU;AAAA,qBACtD,KAAK,SAAS,IAAI,WAAW,YAAa,MAAK,kBAAkB;AAAA,gBACrE,MAAK,IAAI;AAAA,UAChB,CAAC;AACD,cAAI,WAAW,GAAG;AAClB,cAAI,YAAY,OAAO;AAAA,QACzB,GAAG,IAAI;AAAA,IACX,MAAO,SAAQ,MAAM;AACrB,WAAO,MAAM;AACX,aAAO;AACP,WAAK,QAAQ;AAAA,IACf;AAAA,EAEF,GAAG,CAAC,KAAK,IAAI,CAAC;AAId,QAAM,CAAC,QAAQ,SAAS,IAAU,eAAS,MAAM,CAAC,mBAAmB,OAAO,yBAAyB,WAAW;AAGhH,EAAM,gBAAU,MAAM;AACpB,UAAM,UAAU,MAAM;AACtB,QAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAQ;AACjC,eAAW,OAAO;AAAA,EACpB,GAAG,CAAC,KAAK,MAAM,CAAC;AAGhB,EAAM,gBAAU,MAAM;AACpB,UAAM,UAAU,MAAM;AACtB,QAAI,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,UAAU,CAAC,OAAQ;AACxD,eAAW,OAAO;AAAA,EACpB,GAAG,CAAC,KAAK,UAAU,QAAQ,MAAM,CAAC;AAElC,EAAM,gBAAU,MAAM;AACpB,QAAI,MAAM,QAAS,WAAU,MAAM,SAAS,OAAO;AAAA,EACrD,GAAG,CAAC,SAAS,OAAO,MAAM,CAAC;AAE3B,EAAM,gBAAU,MAAM;AACpB,UAAM,SAAS,MAAM,cAAc,SAAS,sBAAsB,KAAK,OAAO;AAC9E,aAAS,iBAAiB,oBAAoB,MAAM;AACpD,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,MAAM;AAAA,EACtE,GAAG,CAAC,CAAC;AACL,EAAM,gBAAU,MAAM,MAAM,aAAa,UAAU,OAAO,GAAG,CAAC,CAAC;AAE/D;AAAA,IACE;AAAA,IACA,CAAC,YAAY;AACX,gBAAU,OAAO;AACjB,UAAI,CAAC,WAAW,MAAM,WAAW,CAAC,MAAM,QAAQ,OAAQ,OAAM,QAAQ,MAAM;AAAA,IAC9E;AAAA,IACA;AAAA,EACF;AAEA,QAAM,OAAO,MAAM;AACjB,cAAU,IAAI;AACd,cAAU,KAAK;AACf,eAAW,MAAM,OAAO;AAAA,EAC1B;AACA,QAAM,SAAS,MAAO,UAAU,MAAM,SAAS,MAAM,IAAI,KAAK;AAC9D,QAAM,OAAO,CAAC,OAAe;AAC3B,QAAI,CAAC,MAAM,QAAS;AACpB,UAAM,QAAQ,cAAc,MAAM,IAAI,GAAG,YAAY,MAAM,QAAQ,YAAY,CAAC;AAChF,YAAQ,MAAM,QAAQ,WAAW;AAAA,EACnC;AACA,QAAM,eAAe,CAAC,OAAe;AACnC,QAAI,CAAC,MAAM,QAAS;AACpB,UAAM,OAAO,MAAM,IAAI,GAAG,CAAC;AAC3B,UAAM,QAAQ,SAAS;AACvB,UAAM,QAAQ,QAAQ,SAAS;AAC/B,cAAU,IAAI;AACd,aAAS,SAAS,CAAC;AAAA,EACrB;AACA,QAAM,aAAa,MAAM;AACvB,QAAI,CAAC,MAAM,QAAS;AACpB,QAAI,SAAS,WAAW,EAAG,cAAa,GAAG;AAC3C,UAAM,QAAQ,QAAQ,CAAC;AACvB,aAAS,CAAC,KAAK;AAAA,EACjB;AACA,QAAM,YAAY,MAAM;AACtB,UAAM,OAAO,eAAe,cAAc,QAAQ,IAAI,IAAI,KAAK,cAAc,MAAM,KAAK;AACxF,QAAI,MAAM,QAAS,OAAM,QAAQ,eAAe;AAChD,YAAQ,IAAI;AAAA,EACd;AACA,QAAM,eAAe,MAAM,OAAO,SAAS,KAAK,WAAW,CAAC,OAAO,IAAI,MAAM,OAAO,SAAS,KAAK,CAAC;AACnG,QAAM,mBAAmB,MAAM;AAC7B,UAAM,UAAU,KAAK;AACrB,QAAI,CAAC,QAAS;AACd,QAAI,SAAS,kBAAmB,MAAK,SAAS,eAAe;AAAA,aACpD,QAAQ,kBAAmB,MAAK,QAAQ,kBAAkB;AAAA,QAC9D,CAAC,MAAM,SAAuE,wBAAwB;AAAA,EAC7G;AACA,QAAM,MAAM,MAAM;AAChB,QAAI,SAAS,wBAAyB,MAAK,SAAS,qBAAqB;AAAA,QACpE,MAAK,MAAM,SAAS,0BAA0B;AAAA,EACrD;AACA,QAAM,OAAO,MAAM;AACjB,YAAQ,KAAK;AACb,iBAAa,UAAU,OAAO;AAC9B,QAAI,QAAS,WAAU,UAAU,WAAW,MAAM,QAAQ,IAAI,GAAG,IAAI;AAAA,EACvE;AAEA,QAAM,YAAY,CAAC,UAA+B;AAChD,UAAM,SAAS,MAAM;AACrB,UAAM,YAAY,OAAO,aAAa,MAAM,MAAM;AAClD,UAAM,MAAM,MAAM,IAAI,WAAW,IAAI,MAAM,IAAI,YAAY,IAAI,MAAM;AACrE,UAAM,MAAM,MAAM,SAAS,eAAe;AAC1C,UAAM,UAAoD;AAAA,MACxD,KAAK,OAAO,YAAY,WAAW,SAAY;AAAA,MAC/C,GAAG;AAAA,MACH,GAAG,MAAM,KAAK,MAAM,EAAE;AAAA,MACtB,GAAG,MAAM,KAAK,MAAM,EAAE;AAAA,MACtB,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG,OAAO,SAAS,eAAe;AAAA,MAClC,WAAW,YAAY,SAAY,MAAM,KAAK,MAAM,CAAC;AAAA,MACrD,YAAY,YAAY,SAAY,MAAM,KAAK,MAAM,CAAC;AAAA,MACtD,SAAS,YAAY,SAAY,MAAM,aAAa,SAAS,GAAG;AAAA,MAChE,WAAW,YAAY,SAAY,MAAM,aAAa,SAAS,GAAG;AAAA,MAClE,MAAM,YAAY,SAAY,MAAM,KAAK,CAAC;AAAA,MAC1C,KAAK,YAAY,SAAY,MAAM,KAAK,QAAQ;AAAA,IAClD;AACA,UAAM,SAAS,UAAU,KAAK,GAAG,KAAK,CAAC,YAAY,MAAM,KAAM,OAAO,GAAG,IAAI,KAAM,QAAQ,IAAI,QAAQ,GAAG;AAC1G,QAAI,CAAC,UAAU,MAAM,WAAW,MAAM,WAAW,MAAM,OAAQ;AAC/D,UAAM,eAAe;AACrB,WAAO;AACP,SAAK;AAAA,EACP;AAEA,QAAM,eAAe,YAAY,CAAC;AAClC,QAAM,eAAe,OAAO,aAAa,eAAe,6BAA6B,YAAY,SAAS;AAE1G,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,UAAU,eAAe,IAAI;AAAA,MAC7B,aAAW,QAAQ,UAAU,KAAK;AAAA,MAClC,cAAY,UAAU,YAAY;AAAA,MAClC,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC;AAAA,MAC/B,OAAO,EAAE,YAAY;AAAA,MACrB,WAAW,eAAe,YAAY;AAAA,MACtC,eAAe,eAAe,OAAO;AAAA,MACrC,gBAAgB,MAAM,WAAW,QAAQ,IAAI;AAAA,MAE7C;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAW,EAAE,MAAM;AAAA,YACnB;AAAA,YACA;AAAA,YACA;AAAA,YACA,aAAW;AAAA,YACX,aAAa,OAAO,SAAS,cAAc;AAAA,YAC3C,SAAS,eAAe,SAAS;AAAA,YACjC,QAAQ,MAAM;AACZ,yBAAW,IAAI;AACf,yBAAW,IAAI;AACf,mBAAK;AACL,uBAAS;AAAA,YACX;AAAA,YACA,SAAS,MAAM;AACb,yBAAW,KAAK;AAChB,sBAAQ,KAAK;AACb,wBAAU;AAAA,YACZ;AAAA,YACA,SAAS,MAAM,UAAU;AAAA,YACzB,cAAc,CAAC,UAAU;AACvB,sBAAQ,MAAM,cAAc,WAAW;AACvC,6BAAe,MAAM,cAAc,WAAW;AAAA,YAChD;AAAA,YACA,kBAAkB,CAAC,UAAU,YAAY,OAAO,SAAS,MAAM,cAAc,QAAQ,IAAI,MAAM,cAAc,WAAW,CAAC;AAAA,YACzH,WAAW,MAAM,WAAW,IAAI;AAAA,YAChC,WAAW,MAAM,WAAW,KAAK;AAAA,YACjC,WAAW,MAAM,WAAW,KAAK;AAAA,YACjC,SAAS,CAAC,UAAU;AAClB,wBAAU,IAAI;AACd,wBAAU,MAAM,cAAc,KAAK;AAAA,YACrC;AAAA,YAEC,iBAAO,IAAI,CAAC,UACX,oBAAC,WAAsB,KAAK,MAAM,KAAK,SAAS,MAAM,SAAS,OAAO,MAAM,OAAO,MAAM,MAAM,QAAQ,aAAa,SAAS,MAAM,WAAvH,MAAM,GAA0H,CAC7I;AAAA;AAAA,QACH;AAAA,QAEC,UAAU,CAAC,UAAU,oBAAC,SAAI,KAAK,QAAQ,KAAI,IAAG,eAAW,MAAC,UAAS,SAAQ,WAAW,EAAE,OAAO,GAAG,IAAK;AAAA,QAEvG,gBAAgB,CAAC,WAAW,CAAC,UAAU,CAAC,WACvC,oBAAC,YAAO,MAAK,UAAS,WAAW,EAAE,IAAI,GAAG,cAAY,OAAO,MAAM,SAAS,MAC1E,8BAAC,aAAU,WAAU,gBAAe,GACtC;AAAA,QAGD,WAAW,CAAC,UACX,qBAAC,SAAI,WAAU,8EACb;AAAA,8BAAC,UAAK,WAAW,EAAE,QAAQ,GAAG,eAAW,MAAC;AAAA,UAC1C,oBAAC,UAAK,MAAK,UAAS,WAAU,WAC3B,iBAAO,SACV;AAAA,WACF;AAAA,QAGD,UACC,qBAAC,SAAI,MAAK,SAAQ,WAAW,EAAE,OAAO,GACpC;AAAA,8BAAC,OAAG,iBAAO,OAAM;AAAA,UACjB;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAW,EAAE,OAAO,EAAE,WAAW,oCAAoC,CAAC;AAAA,cACtE,SAAS,MAAM;AACb,0BAAU,KAAK;AACf,2BAAW,CAAC,MAAM,IAAI,CAAC;AACvB,sBAAM,SAAS,KAAK;AAAA,cACtB;AAAA,cAEA;AAAA,oCAAC,cAAW,WAAU,WAAU;AAAA,gBAC/B,OAAO;AAAA;AAAA;AAAA,UACV;AAAA,WACF;AAAA,QAGD,UAAU,oBAAC,SAAI,WAAW,EAAE,QAAQ,GAAI,mBAAQ,IAAS;AAAA,QAEzD,gBACC,qBAAC,SAAI,WAAW,EAAE,IAAI,GACpB;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,OAAO;AAAA,cACd,KAAK;AAAA,cACL,KAAK,YAAY;AAAA,cACjB,MAAM;AAAA,cACN,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AAAA,cACnC,eAAe;AAAA,cACf,aAAa,CAAC,MAAM,OAAO,KAAK,YAAY,CAAC,GAAG,YAAY,QAAQ,CAAC;AAAA,cACrE,UAAU,CAAC;AAAA,cACX,WAAU;AAAA;AAAA,UACZ;AAAA,UACA,qBAAC,SAAI,WAAW,EAAE,IAAI,GACpB;AAAA,gCAAC,YAAO,MAAK,UAAS,WAAW,EAAE,OAAO,GAAG,cAAY,UAAU,OAAO,QAAQ,OAAO,MAAM,SAAS,QACrG,oBAAU,oBAAC,cAAW,WAAU,WAAU,IAAK,oBAAC,aAAU,WAAU,WAAU,GACjF;AAAA,YACA,oBAAC,YAAO,MAAK,UAAS,WAAW,EAAE,OAAO,GAAG,cAAY,QAAQ,OAAO,SAAS,OAAO,MAAM,SAAS,YACrG,8BAAC,eAAY,OAAc,WAAU,WAAU,GACjD;AAAA,YACA,oBAAC,SAAI,WAAW,EAAE,OAAO,GACvB,8BAAC,UAAO,OAAO,OAAO,QAAQ,KAAK,GAAG,KAAK,GAAG,MAAM,MAAM,OAAO,QAAQ,IAAI,QAAQ,eAAe,cAAc,aAAa,CAAC,MAAM,GAAG,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,WAAU,UAAS,GACvL;AAAA,YACA,qBAAC,UAAK,WAAW,EAAE,KAAK,GAAG,eAAW,MACnC;AAAA,0BAAY,IAAI;AAAA,cAAE;AAAA,cAAI,YAAY,QAAQ;AAAA,eAC7C;AAAA,YACA,oBAAC,UAAK,WAAU,UAAS;AAAA,YACxB,cAAc,SAAS,KACtB,qBAAC,YAAO,MAAK,UAAS,WAAW,EAAE,OAAO,GAAG,cAAY,OAAO,MAAM,IAAI,GAAG,SAAS,WACnF;AAAA;AAAA,cAAK;AAAA,eACR;AAAA,YAED,OAAO,SAAS,KACf,oBAAC,YAAO,MAAK,UAAS,WAAW,EAAE,OAAO,GAAG,gBAAc,WAAW,GAAG,cAAY,OAAO,SAAS,WAAW,IAAK,OAAO,OAAO,GAAG,SAAS,OAAQ,IAAI,GAAG,SAAS,cACrK,8BAAC,iBAAc,WAAU,WAAU,GACrC;AAAA,YAED,gBACC,oBAAC,YAAO,MAAK,UAAS,WAAW,EAAE,OAAO,GAAG,cAAY,OAAO,kBAAkB,SAAS,KACzF,8BAAC,YAAS,WAAU,WAAU,GAChC;AAAA,YAEF,oBAAC,YAAO,MAAK,UAAS,WAAW,EAAE,OAAO,GAAG,cAAY,aAAa,OAAO,iBAAiB,OAAO,YAAY,SAAS,kBACxH,8BAAC,mBAAgB,MAAM,YAAY,WAAU,WAAU,GACzD;AAAA,aACF;AAAA,WACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../src/video-player/video-player.tsx"],"sourcesContent":["// Client. A `<video>` with its own controls, accessible from end to end: a named region the keyboard reaches (Space /\n// K, arrows, J / L, M, F, C, Home / End, 0–9), every button named by a prop, the seek and volume sliders of\n// `@krizaka/ui/slider` with the time read aloud. HLS plays natively where the browser can (Safari, iOS) and through\n// hls.js elsewhere — loaded only then, by the app's `loadHls` (`() => import(\"hls.js\")`): an optional peer, never in\n// the bundle of a page that does not play HLS. A signed address can be resolved at the last moment (`src` as a\n// function), again after an error; the video pauses when it leaves the screen; autoplay waits under reduced motion.\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { CaptionsGlyph, FullscreenGlyph, PauseGlyph, PipGlyph, PlayGlyph, RetryGlyph, VolumeGlyph } from \"../glyphs\";\nimport { clamp, formatClock, playSafely, useInView, usePrefersReducedMotion } from \"../media\";\nimport { Slider } from \"../slider\";\n\nexport const videoPlayer = tv({\n slots: {\n root:\n \"theme-dark group/player relative isolate w-full overflow-hidden rounded-xl bg-media text-fg-on-media \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring data-[idle]:cursor-none\",\n video: \"absolute inset-0 h-full w-full object-contain\",\n poster: \"pointer-events-none absolute inset-0 h-full w-full object-contain\",\n big:\n \"absolute left-1/2 top-1/2 z-10 inline-flex h-16 w-16 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full \" +\n \"bg-scrim-strong text-fg-on-media shadow-lg backdrop-blur-sm transition-colors hover:bg-scrim motion-reduce:transition-none \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n bar:\n \"absolute inset-x-0 bottom-0 z-20 flex flex-col gap-1 bg-linear-to-t from-scrim-strong via-scrim to-transparent px-3 pb-2 pt-10 \" +\n \"transition-opacity duration-300 motion-reduce:transition-none group-data-[idle]/player:opacity-0 group-focus-within/player:opacity-100\",\n row: \"flex items-center gap-1\",\n button:\n \"inline-flex h-9 min-w-9 shrink-0 items-center justify-center gap-1 rounded-md px-1.5 text-xs font-semibold text-fg-on-media \" +\n \"transition-colors hover:bg-fg-on-media/15 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring aria-pressed:bg-fg-on-media/20\",\n time: \"px-1.5 font-mono text-[11px] tabular-nums text-fg-on-media\",\n volume: \"hidden w-20 items-center sm:flex\",\n status: \"absolute inset-0 z-30 flex flex-col items-center justify-center gap-3 bg-scrim-strong p-6 text-center text-sm\",\n spinner: \"h-10 w-10 animate-spin rounded-full border-2 border-fg-on-media/30 border-t-fg-on-media motion-reduce:animate-none\",\n overlay: \"absolute inset-0 z-30\",\n },\n});\n\n/** What `loadHls` resolves to: the module of hls.js (only the members the player uses are typed). */\nexport type HlsModule = {\n default: {\n new (config?: Record<string, unknown>): {\n loadSource(url: string): void;\n attachMedia(media: HTMLMediaElement): void;\n destroy(): void;\n startLoad(): void;\n recoverMediaError(): void;\n on(event: string, listener: (event: string, data: { fatal?: boolean; type?: string }) => void): void;\n };\n isSupported(): boolean;\n Events: { ERROR: string };\n ErrorTypes: { NETWORK_ERROR: string; MEDIA_ERROR: string };\n };\n};\n\nexport type VideoTrack = {\n /** The WebVTT file. */\n src: string;\n /** Its language, BCP 47 (`\"fr\"`). */\n srcLang: string;\n /** Its name in the menu (\"Français\"), passed translated. */\n label: string;\n /** `subtitles` (default) or `captions` (with the sounds, for deaf viewers). */\n kind?: \"subtitles\" | \"captions\";\n /** Shown from the start. */\n default?: boolean;\n};\n\nexport type VideoPlayerLabels = {\n play: string;\n pause: string;\n mute: string;\n unmute: string;\n volume: string;\n seek: string;\n /** The speed button: `(rate) => \"Speed \" + rate + \"×\"`. */\n speed: (rate: number) => string;\n /** The captions button: `(track) => \"Subtitles: \" + (track ?? \"off\")`, the track's label or `null` when off. */\n captions: (track: string | null) => string;\n fullscreen: string;\n exitFullscreen: string;\n pictureInPicture: string;\n /** Read while the video waits for data. */\n loading: string;\n /** The video cannot play. */\n error: string;\n /** Tries again (resolves a signed `src` again). */\n retry: string;\n /** The seek slider's value: `(time, duration) => \"1:05 of 3:20\"`. */\n time: (time: string, duration: string) => string;\n};\n\nexport const videoPlayerLabels: VideoPlayerLabels = {\n play: \"Play\",\n pause: \"Pause\",\n mute: \"Mute\",\n unmute: \"Unmute\",\n volume: \"Volume\",\n seek: \"Seek\",\n speed: (rate) => `Speed ${rate}×`,\n captions: (track) => `Subtitles: ${track ?? \"off\"}`,\n fullscreen: \"Full screen\",\n exitFullscreen: \"Exit full screen\",\n pictureInPicture: \"Picture in picture\",\n loading: \"Loading\",\n error: \"This video cannot be played.\",\n retry: \"Try again\",\n time: (time, duration) => `${time} of ${duration}`,\n};\n\nexport type VideoPlayerProps = {\n /** The address of the video (MP4, WebM, or an HLS `.m3u8`), or a function that resolves a signed one when needed. */\n src: string | (() => Promise<string>);\n /** `auto` (default): HLS when the address ends in `.m3u8`. */\n type?: \"auto\" | \"hls\" | \"file\";\n /** Loads hls.js when the browser cannot play HLS itself: `() => import(\"hls.js\")`. Without it, HLS needs Safari. */\n loadHls?: () => Promise<HlsModule>;\n /** The accessible name of the player (\"Video: Sunset over Montréal\"), passed translated. */\n title: string;\n /** The picture shown before playback. */\n poster?: string;\n /** Starts playing, muted (browsers refuse sound without a gesture), once on screen and again each time it comes back — not under reduced motion. */\n autoPlay?: boolean;\n /** Starts muted. */\n muted?: boolean;\n /** Plays again from the start at the end. */\n loop?: boolean;\n /** How much to fetch before playback: `none` (a list of many videos), `metadata` (default), `auto`. */\n preload?: \"none\" | \"metadata\" | \"auto\";\n /** Subtitles or captions (WebVTT): the C key and a button cycle through them. */\n tracks?: readonly VideoTrack[];\n /** The speeds offered by the speed button. Default `[0.5, 1, 1.25, 1.5, 2]`. */\n playbackRates?: readonly number[];\n /** Pauses when less than a quarter of the player is on screen. Default `true`. */\n pauseWhenHidden?: boolean;\n /** Shows the controls (default). `false`: a bare video (a background loop) — give it no sound. */\n controls?: boolean;\n /** Covers the video and hides the controls: a gate (sign in, unlock, age check) drawn by the app. */\n overlay?: React.ReactNode;\n /** The width / height ratio of the frame. Default `\"16 / 9\"`; `\"9 / 16\"` for a vertical video. */\n aspectRatio?: string;\n /** Called when playback starts. */\n onPlay?: () => void;\n /** Called when playback pauses. */\n onPause?: () => void;\n /** Called at the end. */\n onEnded?: () => void;\n /** Called as the time moves, in seconds (a few times a second). */\n onTimeUpdate?: (time: number) => void;\n /** Called when the video cannot play (a network failure, an expired address). */\n onError?: (error: unknown) => void;\n /** The words, passed translated; English by default. */\n labels?: Partial<VideoPlayerLabels>;\n /** Classes merged on the root. */\n className?: string;\n};\n\nconst RATES = [0.5, 1, 1.25, 1.5, 2] as const;\nconst isHls = (url: string, type: VideoPlayerProps[\"type\"]) => type === \"hls\" || (type !== \"file\" && /\\.m3u8(\\?|#|$)/i.test(url));\n\n/** Shows the text track `index` of a video (and hides the others); -1 hides them all. */\nfunction showTrack(element: HTMLVideoElement, index: number) {\n const list = element.textTracks;\n for (let i = 0; i < list.length; i += 1) list[i]!.mode = i === index ? \"showing\" : \"disabled\";\n}\n\n/** A video player with accessible controls, HLS on demand, signed sources, subtitles, speed, full screen. */\nexport function VideoPlayer({\n src,\n type = \"auto\",\n loadHls,\n title,\n poster,\n autoPlay,\n muted: initiallyMuted = false,\n loop,\n preload = \"metadata\",\n tracks = [],\n playbackRates = RATES,\n pauseWhenHidden = true,\n controls = true,\n overlay,\n aspectRatio = \"16 / 9\",\n onPlay,\n onPause,\n onEnded,\n onTimeUpdate,\n onError,\n labels: given,\n className,\n}: VideoPlayerProps) {\n const labels = { ...videoPlayerLabels, ...given };\n const s = videoPlayer();\n const root = React.useRef<HTMLDivElement>(null);\n const video = React.useRef<HTMLVideoElement>(null);\n const reduce = usePrefersReducedMotion();\n const [resolved, setResolved] = React.useState<{ attempt: number; url: string } | null>(null);\n const [attempt, setAttempt] = React.useState(0);\n const [wanted, setWanted] = React.useState(false);\n const [playing, setPlaying] = React.useState(false);\n const [time, setTime] = React.useState(0);\n const [duration, setDuration] = React.useState(0);\n const [volume, setVolume] = React.useState(1);\n const [muted, setMuted] = React.useState(initiallyMuted || Boolean(autoPlay));\n const [rate, setRate] = React.useState(1);\n const [caption, setCaption] = React.useState(() => tracks.findIndex((t) => t.default));\n const [fullscreen, setFullscreen] = React.useState(false);\n const [waiting, setWaiting] = React.useState(false);\n const [failed, setFailed] = React.useState(false);\n const [idle, setIdle] = React.useState(false);\n // The poster is an image over the video until the first play: it loads like any image (lazy, decoded once), the\n // same in every browser — the `poster` attribute is painted late and differently.\n const [started, setStarted] = React.useState(false);\n const idleTimer = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const url = typeof src === \"string\" ? src : resolved?.attempt === attempt ? resolved.url : null;\n const needSource = typeof src === \"function\" && (preload !== \"none\" || wanted || (autoPlay && !reduce));\n\n // A signed source is resolved when it is needed, and again on \"Try again\".\n React.useEffect(() => {\n if (typeof src !== \"function\" || !needSource) return;\n let live = true;\n src().then(\n (next) => live && setResolved({ attempt, url: next }),\n (error: unknown) => {\n if (!live) return;\n setFailed(true);\n onError?.(error);\n },\n );\n return () => {\n live = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `onError` is a callback, not a reason to resolve again\n }, [src, needSource, attempt]);\n\n // Attaches the source: natively, or through hls.js when the browser needs it.\n React.useEffect(() => {\n const element = video.current;\n if (!element || !url) return;\n let hls: InstanceType<HlsModule[\"default\"]> | null = null;\n let live = true;\n const fail = (error: unknown) => {\n if (!live) return;\n setFailed(true);\n onError?.(error);\n };\n if (isHls(url, type) && !element.canPlayType(\"application/vnd.apple.mpegurl\")) {\n if (!loadHls) fail(new Error(\"VideoPlayer: HLS needs `loadHls` in this browser.\"));\n else\n loadHls().then(({ default: Hls }) => {\n if (!live) return;\n if (!Hls.isSupported()) return fail(new Error(\"VideoPlayer: HLS is not supported here.\"));\n hls = new Hls({ enableWorker: true, backBufferLength: 60 });\n hls.on(Hls.Events.ERROR, (_event, data) => {\n if (!data.fatal) return;\n if (data.type === Hls.ErrorTypes.NETWORK_ERROR) hls?.startLoad();\n else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) hls?.recoverMediaError();\n else fail(data);\n });\n hls.loadSource(url);\n hls.attachMedia(element);\n }, fail);\n } else element.src = url;\n return () => {\n live = false;\n hls?.destroy();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- `onError` and `loadHls` are callbacks\n }, [url, type]);\n\n // An autoplay waits for the player to be on screen (nothing is fetched before, with `preload=\"none\"`), and plays\n // again each time it comes back: a page of loops costs only the ones in view.\n const [inView, setInView] = React.useState(() => !pauseWhenHidden || typeof IntersectionObserver === \"undefined\");\n\n // Plays once the source is there, when it was asked for (a click before a signed source resolved).\n React.useEffect(() => {\n const element = video.current;\n if (!element || !url || !wanted) return;\n playSafely(element);\n }, [url, wanted]);\n\n // An autoplay: while in view, never under reduced motion.\n React.useEffect(() => {\n const element = video.current;\n if (!element || !url || !autoPlay || reduce || !inView) return;\n playSafely(element);\n }, [url, autoPlay, reduce, inView]);\n\n React.useEffect(() => {\n if (video.current) showTrack(video.current, caption);\n }, [caption, tracks.length]);\n\n React.useEffect(() => {\n const change = () => setFullscreen(document.fullscreenElement === root.current);\n document.addEventListener(\"fullscreenchange\", change);\n return () => document.removeEventListener(\"fullscreenchange\", change);\n }, []);\n React.useEffect(() => () => clearTimeout(idleTimer.current), []);\n\n useInView(\n root,\n (visible) => {\n setInView(visible);\n if (!visible && video.current && !video.current.paused) video.current.pause();\n },\n pauseWhenHidden,\n );\n\n const play = () => {\n setWanted(true);\n setFailed(false);\n playSafely(video.current);\n };\n const toggle = () => (playing ? video.current?.pause() : play());\n const seek = (to: number) => {\n if (!video.current) return;\n video.current.currentTime = clamp(to, 0, duration || video.current.duration || 0);\n setTime(video.current.currentTime);\n };\n const changeVolume = (to: number) => {\n if (!video.current) return;\n const next = clamp(to, 0, 1);\n video.current.volume = next;\n video.current.muted = next === 0;\n setVolume(next);\n setMuted(next === 0);\n };\n const toggleMute = () => {\n if (!video.current) return;\n if (muted && volume === 0) changeVolume(0.5);\n video.current.muted = !muted;\n setMuted(!muted);\n };\n const cycleRate = () => {\n const next = playbackRates[(playbackRates.indexOf(rate) + 1) % playbackRates.length] ?? 1;\n if (video.current) video.current.playbackRate = next;\n setRate(next);\n };\n const cycleCaption = () => tracks.length > 0 && setCaption((c) => (c + 2) % (tracks.length + 1) - 1);\n const toggleFullscreen = () => {\n const element = root.current;\n if (!element) return;\n if (document.fullscreenElement) void document.exitFullscreen();\n else if (element.requestFullscreen) void element.requestFullscreen();\n else (video.current as HTMLVideoElement & { webkitEnterFullscreen?: () => void })?.webkitEnterFullscreen?.();\n };\n const pip = () => {\n if (document.pictureInPictureElement) void document.exitPictureInPicture();\n else void video.current?.requestPictureInPicture?.();\n };\n const wake = () => {\n setIdle(false);\n clearTimeout(idleTimer.current);\n if (playing) idleTimer.current = setTimeout(() => setIdle(true), 2500);\n };\n\n const onKeyDown = (event: React.KeyboardEvent) => {\n const target = event.target as HTMLElement;\n const inControl = target.getAttribute(\"role\") === \"slider\";\n const key = event.key.length === 1 ? event.key.toLowerCase() : event.key;\n const now = video.current?.currentTime ?? 0;\n const actions: Record<string, (() => void) | undefined> = {\n \" \": target.tagName === \"BUTTON\" ? undefined : toggle,\n k: toggle,\n j: () => seek(now - 10),\n l: () => seek(now + 10),\n m: toggleMute,\n f: toggleFullscreen,\n c: tracks.length ? cycleCaption : undefined,\n ArrowLeft: inControl ? undefined : () => seek(now - 5),\n ArrowRight: inControl ? undefined : () => seek(now + 5),\n ArrowUp: inControl ? undefined : () => changeVolume(volume + 0.1),\n ArrowDown: inControl ? undefined : () => changeVolume(volume - 0.1),\n Home: inControl ? undefined : () => seek(0),\n End: inControl ? undefined : () => seek(duration),\n };\n const action = /^[0-9]$/.test(key) && !inControl ? () => seek((Number(key) / 10) * duration) : actions[key];\n if (!action || event.metaKey || event.ctrlKey || event.altKey) return;\n event.preventDefault();\n action();\n wake();\n };\n\n const showControls = controls && !overlay;\n const pipSupported = typeof document !== \"undefined\" && \"pictureInPictureEnabled\" in document && document.pictureInPictureEnabled;\n\n return (\n <div\n ref={root}\n role=\"region\"\n aria-label={title}\n tabIndex={showControls ? 0 : undefined}\n data-idle={idle && playing ? \"\" : undefined}\n data-state={playing ? \"playing\" : \"paused\"}\n className={s.root({ className })}\n style={{ aspectRatio }}\n onKeyDown={showControls ? onKeyDown : undefined}\n onPointerMove={showControls ? wake : undefined}\n onPointerLeave={() => playing && setIdle(true)}\n >\n <video\n ref={video}\n className={s.video()}\n preload={preload}\n loop={loop}\n muted={muted}\n playsInline\n crossOrigin={tracks.length ? \"anonymous\" : undefined}\n onClick={showControls ? toggle : undefined}\n onPlay={() => {\n setStarted(true);\n setPlaying(true);\n wake();\n onPlay?.();\n }}\n onPause={() => {\n setPlaying(false);\n setIdle(false);\n onPause?.();\n }}\n onEnded={() => onEnded?.()}\n onTimeUpdate={(event) => {\n setTime(event.currentTarget.currentTime);\n onTimeUpdate?.(event.currentTarget.currentTime);\n }}\n onDurationChange={(event) => setDuration(Number.isFinite(event.currentTarget.duration) ? event.currentTarget.duration : 0)}\n onWaiting={() => setWaiting(true)}\n onPlaying={() => setWaiting(false)}\n onCanPlay={() => setWaiting(false)}\n onError={(event) => {\n setFailed(true);\n onError?.(event.currentTarget.error);\n }}\n >\n {tracks.map((track) => (\n <track key={track.src} src={track.src} srcLang={track.srcLang} label={track.label} kind={track.kind ?? \"subtitles\"} default={track.default} />\n ))}\n </video>\n\n {poster && !started ? <img src={poster} alt=\"\" aria-hidden decoding=\"async\" className={s.poster()} /> : null}\n\n {showControls && !playing && !failed && !waiting && (\n <button type=\"button\" className={s.big()} aria-label={labels.play} onClick={play}>\n <PlayGlyph className=\"ml-1 h-7 w-7\" />\n </button>\n )}\n\n {waiting && !failed && (\n <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center\">\n <span className={s.spinner()} aria-hidden />\n <span role=\"status\" className=\"sr-only\">\n {labels.loading}\n </span>\n </div>\n )}\n\n {failed && (\n <div role=\"alert\" className={s.status()}>\n <p>{labels.error}</p>\n <button\n type=\"button\"\n className={s.button({ className: \"border border-fg-on-media/40 px-3\" })}\n onClick={() => {\n setFailed(false);\n setAttempt((a) => a + 1);\n video.current?.load();\n }}\n >\n <RetryGlyph className=\"h-4 w-4\" />\n {labels.retry}\n </button>\n </div>\n )}\n\n {overlay ? <div className={s.overlay()}>{overlay}</div> : null}\n\n {showControls && (\n <div className={s.bar()}>\n <Slider\n label={labels.seek}\n min={0}\n max={duration || 1}\n step={0.1}\n value={Math.min(time, duration || 1)}\n onValueChange={seek}\n formatValue={(v) => labels.time(formatClock(v), formatClock(duration))}\n disabled={!duration}\n className=\"[&_[role=slider]]:h-4 [&_[role=slider]]:w-4\"\n />\n <div className={s.row()}>\n <button type=\"button\" className={s.button()} aria-label={playing ? labels.pause : labels.play} onClick={toggle}>\n {playing ? <PauseGlyph className=\"h-5 w-5\" /> : <PlayGlyph className=\"h-5 w-5\" />}\n </button>\n <button type=\"button\" className={s.button()} aria-label={muted ? labels.unmute : labels.mute} onClick={toggleMute}>\n <VolumeGlyph muted={muted} className=\"h-5 w-5\" />\n </button>\n <div className={s.volume()}>\n <Slider label={labels.volume} min={0} max={1} step={0.05} value={muted ? 0 : volume} onValueChange={changeVolume} formatValue={(v) => `${Math.round(v * 100)} %`} className=\"w-full\" />\n </div>\n <span className={s.time()} aria-hidden>\n {formatClock(time)} / {formatClock(duration)}\n </span>\n <span className=\"flex-1\" />\n {playbackRates.length > 1 && (\n <button type=\"button\" className={s.button()} aria-label={labels.speed(rate)} onClick={cycleRate}>\n {rate}×\n </button>\n )}\n {tracks.length > 0 && (\n <button type=\"button\" className={s.button()} aria-pressed={caption >= 0} aria-label={labels.captions(caption >= 0 ? (tracks[caption]?.label ?? null) : null)} onClick={cycleCaption}>\n <CaptionsGlyph className=\"h-5 w-5\" />\n </button>\n )}\n {pipSupported && (\n <button type=\"button\" className={s.button()} aria-label={labels.pictureInPicture} onClick={pip}>\n <PipGlyph className=\"h-5 w-5\" />\n </button>\n )}\n <button type=\"button\" className={s.button()} aria-label={fullscreen ? labels.exitFullscreen : labels.fullscreen} onClick={toggleFullscreen}>\n <FullscreenGlyph exit={fullscreen} className=\"h-5 w-5\" />\n </button>\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@krizaka/ui",
3
- "version": "3.29.0",
3
+ "version": "3.31.0",
4
4
  "description": "The Krizaka front-end platform's components: the primitives (button, card, dialog, toast, menu, field, tabs, chip, switch, slider, command palette, theme, countdown…) on the semantic --kz-* tokens, the animated marks (Krizaka, Orazaka, Orochia, Yasakia, Yororis) and the motion signature — web and /native.",
5
5
  "keywords": [
6
6
  "krizaka",
@@ -721,7 +721,7 @@
721
721
  ],
722
722
  "peerDependencies": {
723
723
  "@krizaka/query": ">=0.2.1",
724
- "@krizaka/tailwind": ">=3.29.0",
724
+ "@krizaka/tailwind": ">=3.31.0",
725
725
  "@maplibre/maplibre-react-native": ">=11",
726
726
  "@shopify/flash-list": ">=2",
727
727
  "expo-camera": ">=16",
@@ -1242,7 +1242,7 @@
1242
1242
  {
1243
1243
  "name": "./nav-bar (Radix NavigationMenu, Slot, the family's marks)",
1244
1244
  "path": "dist/nav-bar.js",
1245
- "limit": "24.6 kB",
1245
+ "limit": "25.2 kB",
1246
1246
  "gzip": true,
1247
1247
  "ignore": [
1248
1248
  "tailwind-variants",
@@ -2289,7 +2289,7 @@
2289
2289
  {
2290
2290
  "name": "./map",
2291
2291
  "path": "dist/map.js",
2292
- "limit": "16 kB",
2292
+ "limit": "18 kB",
2293
2293
  "gzip": true,
2294
2294
  "ignore": [
2295
2295
  "tailwind-variants",
@@ -2466,7 +2466,7 @@
2466
2466
  "tailwind-variants": "^3.3.1",
2467
2467
  "@krizaka/intl": "^0.2.1",
2468
2468
  "@krizaka/pacer": "^0.1.0",
2469
- "@krizaka/tokens": "^3.29.0"
2469
+ "@krizaka/tokens": "^3.31.0"
2470
2470
  },
2471
2471
  "scripts": {
2472
2472
  "build": "node -e \"const fs=require('node:fs');fs.rmSync('dist',{recursive:true,force:true});for(const f of fs.readdirSync('registry/examples',{recursive:true}))if(/\\.(js|d\\.ts)$/.test(f))fs.rmSync('registry/examples/'+f)\" && tsup && node -e \"require('node:fs').copyFileSync('src/motion.css','dist/motion.css');require('node:fs').copyFileSync('src/blocks.css','dist/blocks.css');require('node:fs').copyFileSync('src/story.css','dist/story.css')\" && node scripts/build-registry.mjs",
@@ -135,7 +135,7 @@
135
135
  "files": [
136
136
  {
137
137
  "path": "action-bar/action-bar.tsx",
138
- "content": "// Server-safe. A row of actions that leave or move on (blocks.css): discuss · propose · report, read the docs, see the\n// code. `buttons`: buttons with their words — the end of a page or a section. `icons`: icon buttons whose words are the\n// accessible name and a tooltip on hover and focus (CSS only: no script, no portal) — the foot of a card.\nimport type * as React from \"react\";\n\nimport { BlockLink, isExternal, type LinkComponent } from \"../block-link\";\nimport { buttonVariants } from \"../button/button\";\nimport { cn } from \"../cn\";\nimport { ExternalGlyph } from \"../glyphs\";\n\nexport interface Action {\n /** Where it leads. An absolute URL opens in a new tab, with the external mark. */\n href: string;\n /** Its words (the accessible name, and the tooltip of an icon action). */\n label: string;\n /** Its icon (a signature icon): decorative. Required by `variant=\"icons\"`. */\n icon?: React.ReactNode;\n}\n\nexport type ActionBarProps = React.HTMLAttributes<HTMLUListElement> & {\n /** The actions, in order of importance. */\n actions: readonly Action[];\n /**\n * `buttons` (with their words) or `icons` (icon buttons, the words in a tooltip).\n * @default \"buttons\"\n */\n variant?: \"buttons\" | \"icons\";\n /**\n * The first action as the primary button (the one action a block is about); the others stay secondary.\n * @default false\n */\n primaryFirst?: boolean;\n /**\n * The buttons' size: `sm` in a card, `md` in a section, `lg` on a hero or a closing call.\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /** What the actions are about (`Talk about Krizaka Java`): the list's accessible name. */\n label?: string;\n /** The app's link component for internal addresses (Next's `Link`); an `<a>` otherwise. */\n linkAs?: LinkComponent;\n};\n\n/** A row of link actions: buttons with their words, or icon buttons with a tooltip. */\nexport function ActionBar({ actions, variant = \"buttons\", primaryFirst = false, size = \"md\", label, linkAs, className, ...props }: ActionBarProps) {\n const icons = variant === \"icons\";\n return (\n <ul className={cn(\"kz-actions\", className)} data-variant={icons ? \"icons\" : undefined} aria-label={label} {...props}>\n {actions.map((a, i) => {\n const external = isExternal(a.href);\n return (\n <li key={a.href}>\n {icons ? (\n <BlockLink\n href={a.href}\n linkAs={linkAs}\n external={external}\n aria-label={a.label}\n data-tip={a.label}\n className={buttonVariants({ variant: \"ghost\", size: \"icon\", shape: \"cut\", className: size === \"sm\" ? \"h-9 w-9\" : undefined })}\n >\n {a.icon}\n </BlockLink>\n ) : (\n <BlockLink\n href={a.href}\n linkAs={linkAs}\n external={external}\n className={buttonVariants({ variant: primaryFirst && i === 0 ? \"primary\" : \"secondary\", size, shape: \"cut\", className: \"gap-2\" })}\n >\n {a.icon}\n {a.label}\n {external && <ExternalGlyph className=\"h-3 w-3 opacity-70\" />}\n </BlockLink>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n"
138
+ "content": "// Server-safe. A row of actions that leave or move on (blocks.css): discuss · propose · report, read the docs, see the\n// code. `buttons`: buttons with their words — the end of a page or a section. `icons`: icon buttons whose words are the\n// accessible name and a tooltip on hover and focus (CSS only: no script, no portal) — the foot of a card.\nimport type * as React from \"react\";\n\nimport { BlockLink, isExternal, type LinkComponent } from \"../block-link\";\nimport { buttonVariants } from \"../button/button\";\nimport { cn } from \"../cn\";\nimport { ExternalGlyph } from \"../glyphs\";\n\nexport interface Action {\n /** Where it leads. An absolute URL opens in a new tab, with the external mark. */\n href: string;\n /** Its words (the accessible name, and the tooltip of an icon action). */\n label: string;\n /** Its icon (a signature icon): decorative. Required by `variant=\"icons\"`. */\n icon?: React.ReactNode;\n}\n\nexport type ActionBarProps = React.HTMLAttributes<HTMLUListElement> & {\n /** The actions, in order of importance. */\n actions: readonly Action[];\n /**\n * `buttons` (with their words) or `icons` (icon buttons, the words in a tooltip).\n * @default \"buttons\"\n */\n variant?: \"buttons\" | \"icons\";\n /**\n * The first action as the primary button (the one action a block is about); the others stay secondary.\n * @default false\n */\n primaryFirst?: boolean;\n /**\n * The buttons' size: `sm` in a card, `md` in a section, `lg` on a hero or a closing call.\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /** What the actions are about (`Talk about Krizaka Java`): the list's accessible name. */\n label?: string;\n /** The app's link component for internal addresses (Next's `Link`); an `<a>` otherwise. */\n linkAs?: LinkComponent;\n};\n\n/** A row of link actions: buttons with their words, or icon buttons with a tooltip. */\nexport function ActionBar({ actions, variant = \"buttons\", primaryFirst = false, size = \"md\", label, linkAs, className, ...props }: ActionBarProps) {\n const icons = variant === \"icons\";\n return (\n <ul className={cn(\"kz-actions\", className)} data-variant={icons ? \"icons\" : undefined} aria-label={label} {...props}>\n {actions.map((a, i) => {\n const external = isExternal(a.href);\n return (\n <li key={a.href}>\n {icons ? (\n <BlockLink\n href={a.href}\n linkAs={linkAs}\n external={external}\n aria-label={a.label}\n data-tip={a.label}\n className={buttonVariants({ variant: \"ghost\", size: \"icon\", className: size === \"sm\" ? \"h-9 w-9\" : undefined })}\n >\n {a.icon}\n </BlockLink>\n ) : (\n <BlockLink\n href={a.href}\n linkAs={linkAs}\n external={external}\n className={buttonVariants({ variant: primaryFirst && i === 0 ? \"primary\" : \"secondary\", size, className: \"gap-2\" })}\n >\n {a.icon}\n {a.label}\n {external && <ExternalGlyph className=\"h-3 w-3 opacity-70\" />}\n </BlockLink>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n"
139
139
  },
140
140
  {
141
141
  "path": "action-bar/index.ts",