tempest-react-sdk 0.47.0 → 0.49.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 (539) hide show
  1. package/dist/audio/sfx-pool.cjs +1 -1
  2. package/dist/audio/sfx-pool.cjs.map +1 -1
  3. package/dist/audio/sfx-pool.js +16 -7
  4. package/dist/audio/sfx-pool.js.map +1 -1
  5. package/dist/audio/use-sfx-pool.cjs +1 -1
  6. package/dist/audio/use-sfx-pool.cjs.map +1 -1
  7. package/dist/audio/use-sfx-pool.js +3 -8
  8. package/dist/audio/use-sfx-pool.js.map +1 -1
  9. package/dist/auth/passkey.cjs +1 -1
  10. package/dist/auth/passkey.cjs.map +1 -1
  11. package/dist/auth/passkey.js +79 -81
  12. package/dist/auth/passkey.js.map +1 -1
  13. package/dist/charts.cjs +1 -1
  14. package/dist/charts.js +4 -4
  15. package/dist/components/AIChat/AIChatTurn.cjs +1 -1
  16. package/dist/components/AIChat/AIChatTurn.js +4 -4
  17. package/dist/components/AppBar/use-sticky-body-warning.cjs.map +1 -1
  18. package/dist/components/AppBar/use-sticky-body-warning.js.map +1 -1
  19. package/dist/components/BarList/BarList.cjs +1 -1
  20. package/dist/components/BarList/BarList.cjs.map +1 -1
  21. package/dist/components/BarList/BarList.js +31 -24
  22. package/dist/components/BarList/BarList.js.map +1 -1
  23. package/dist/components/BarList/bar-list-model.cjs +1 -1
  24. package/dist/components/BarList/bar-list-model.cjs.map +1 -1
  25. package/dist/components/BarList/bar-list-model.js +5 -5
  26. package/dist/components/BarList/bar-list-model.js.map +1 -1
  27. package/dist/components/ClickOutside/ClickOutside.cjs +1 -1
  28. package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
  29. package/dist/components/ClickOutside/ClickOutside.js +13 -14
  30. package/dist/components/ClickOutside/ClickOutside.js.map +1 -1
  31. package/dist/components/DataTable/DataTable.cjs +1 -1
  32. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  33. package/dist/components/DataTable/DataTable.js +131 -129
  34. package/dist/components/DataTable/DataTable.js.map +1 -1
  35. package/dist/components/DataTable/use-dev-warnings.cjs.map +1 -1
  36. package/dist/components/DataTable/use-dev-warnings.js.map +1 -1
  37. package/dist/components/FilterBar/filter-apply.cjs +1 -1
  38. package/dist/components/FilterBar/filter-apply.cjs.map +1 -1
  39. package/dist/components/FilterBar/filter-apply.js +35 -38
  40. package/dist/components/FilterBar/filter-apply.js.map +1 -1
  41. package/dist/components/FilterBar/filter-query.cjs +1 -1
  42. package/dist/components/FilterBar/filter-query.cjs.map +1 -1
  43. package/dist/components/FilterBar/filter-query.js +16 -13
  44. package/dist/components/FilterBar/filter-query.js.map +1 -1
  45. package/dist/components/NotificationCenter/NotificationCenter.cjs +1 -1
  46. package/dist/components/NotificationCenter/NotificationCenter.js +21 -21
  47. package/dist/components/Sidebar/Sidebar.cjs +1 -1
  48. package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
  49. package/dist/components/Sidebar/Sidebar.js +91 -38
  50. package/dist/components/Sidebar/Sidebar.js.map +1 -1
  51. package/dist/components/Sidebar/Sidebar.module.cjs +1 -1
  52. package/dist/components/Sidebar/Sidebar.module.cjs.map +1 -1
  53. package/dist/components/Sidebar/Sidebar.module.js +12 -8
  54. package/dist/components/Sidebar/Sidebar.module.js.map +1 -1
  55. package/dist/forms/masked-inputs.cjs +1 -1
  56. package/dist/forms/masked-inputs.js +12 -12
  57. package/dist/geo/use-position-tracker.cjs +1 -1
  58. package/dist/geo/use-position-tracker.cjs.map +1 -1
  59. package/dist/geo/use-position-tracker.js +25 -26
  60. package/dist/geo/use-position-tracker.js.map +1 -1
  61. package/dist/hooks/use-async.cjs +1 -1
  62. package/dist/hooks/use-async.cjs.map +1 -1
  63. package/dist/hooks/use-async.js +27 -30
  64. package/dist/hooks/use-async.js.map +1 -1
  65. package/dist/hooks/use-click-outside.cjs +1 -1
  66. package/dist/hooks/use-click-outside.cjs.map +1 -1
  67. package/dist/hooks/use-click-outside.js +8 -9
  68. package/dist/hooks/use-click-outside.js.map +1 -1
  69. package/dist/hooks/use-countdown.cjs +1 -1
  70. package/dist/hooks/use-countdown.cjs.map +1 -1
  71. package/dist/hooks/use-countdown.js +8 -13
  72. package/dist/hooks/use-countdown.js.map +1 -1
  73. package/dist/hooks/use-event-listener.cjs +1 -1
  74. package/dist/hooks/use-event-listener.cjs.map +1 -1
  75. package/dist/hooks/use-event-listener.js +6 -6
  76. package/dist/hooks/use-event-listener.js.map +1 -1
  77. package/dist/hooks/use-interval.cjs +1 -1
  78. package/dist/hooks/use-interval.cjs.map +1 -1
  79. package/dist/hooks/use-interval.js +5 -6
  80. package/dist/hooks/use-interval.js.map +1 -1
  81. package/dist/hooks/use-latest-ref.cjs.map +1 -1
  82. package/dist/hooks/use-latest-ref.js.map +1 -1
  83. package/dist/hooks/use-long-press-handlers.cjs +1 -1
  84. package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
  85. package/dist/hooks/use-long-press-handlers.js +8 -10
  86. package/dist/hooks/use-long-press-handlers.js.map +1 -1
  87. package/dist/hooks/use-long-press.cjs +1 -1
  88. package/dist/hooks/use-long-press.cjs.map +1 -1
  89. package/dist/hooks/use-long-press.js +6 -6
  90. package/dist/hooks/use-long-press.js.map +1 -1
  91. package/dist/hooks/use-online.cjs +1 -1
  92. package/dist/hooks/use-online.cjs.map +1 -1
  93. package/dist/hooks/use-online.js +10 -10
  94. package/dist/hooks/use-online.js.map +1 -1
  95. package/dist/hooks/use-service-worker-update.cjs +1 -1
  96. package/dist/hooks/use-service-worker-update.cjs.map +1 -1
  97. package/dist/hooks/use-service-worker-update.js +24 -25
  98. package/dist/hooks/use-service-worker-update.js.map +1 -1
  99. package/dist/hooks/use-stable-callback.cjs +1 -1
  100. package/dist/hooks/use-stable-callback.cjs.map +1 -1
  101. package/dist/hooks/use-stable-callback.js +4 -3
  102. package/dist/hooks/use-stable-callback.js.map +1 -1
  103. package/dist/hooks/use-timeout.cjs +1 -1
  104. package/dist/hooks/use-timeout.cjs.map +1 -1
  105. package/dist/hooks/use-timeout.js +5 -6
  106. package/dist/hooks/use-timeout.js.map +1 -1
  107. package/dist/hooks/use-typewriter.cjs +1 -1
  108. package/dist/hooks/use-typewriter.cjs.map +1 -1
  109. package/dist/hooks/use-typewriter.js +9 -18
  110. package/dist/hooks/use-typewriter.js.map +1 -1
  111. package/dist/http/api-client.cjs +1 -1
  112. package/dist/http/api-client.cjs.map +1 -1
  113. package/dist/http/api-client.js +55 -46
  114. package/dist/http/api-client.js.map +1 -1
  115. package/dist/http/describe-api-error.cjs +1 -1
  116. package/dist/http/describe-api-error.cjs.map +1 -1
  117. package/dist/http/describe-api-error.js +15 -14
  118. package/dist/http/describe-api-error.js.map +1 -1
  119. package/dist/http/errors.cjs +1 -1
  120. package/dist/http/errors.cjs.map +1 -1
  121. package/dist/http/errors.js +49 -20
  122. package/dist/http/errors.js.map +1 -1
  123. package/dist/http/resumable-upload.cjs +1 -1
  124. package/dist/http/resumable-upload.cjs.map +1 -1
  125. package/dist/http/resumable-upload.js +60 -61
  126. package/dist/http/resumable-upload.js.map +1 -1
  127. package/dist/http/retry.cjs +1 -1
  128. package/dist/http/retry.cjs.map +1 -1
  129. package/dist/http/retry.js +20 -16
  130. package/dist/http/retry.js.map +1 -1
  131. package/dist/http/use-describe-api-error.cjs +1 -1
  132. package/dist/http/use-describe-api-error.cjs.map +1 -1
  133. package/dist/http/use-describe-api-error.js +14 -10
  134. package/dist/http/use-describe-api-error.js.map +1 -1
  135. package/dist/i18n/create-i18n.cjs +1 -1
  136. package/dist/i18n/create-i18n.cjs.map +1 -1
  137. package/dist/i18n/create-i18n.js +6 -6
  138. package/dist/i18n/create-i18n.js.map +1 -1
  139. package/dist/icons/Icon.cjs +1 -1
  140. package/dist/icons/Icon.cjs.map +1 -1
  141. package/dist/icons/Icon.js +15 -14
  142. package/dist/icons/Icon.js.map +1 -1
  143. package/dist/icons/IconPicker.cjs +2 -0
  144. package/dist/icons/IconPicker.cjs.map +1 -0
  145. package/dist/icons/IconPicker.js +49 -0
  146. package/dist/icons/IconPicker.js.map +1 -0
  147. package/dist/icons/IconPicker.module.cjs +2 -0
  148. package/dist/icons/IconPicker.module.cjs.map +1 -0
  149. package/dist/icons/IconPicker.module.js +10 -0
  150. package/dist/icons/IconPicker.module.js.map +1 -0
  151. package/dist/icons/alias.cjs +2 -0
  152. package/dist/icons/alias.cjs.map +1 -0
  153. package/dist/icons/alias.js +9 -0
  154. package/dist/icons/alias.js.map +1 -0
  155. package/dist/icons/generated/loaders.cjs +1 -1
  156. package/dist/icons/generated/loaders.cjs.map +1 -1
  157. package/dist/icons/generated/loaders.js +273 -28
  158. package/dist/icons/generated/loaders.js.map +1 -1
  159. package/dist/icons/generated/shard-00.cjs +2 -0
  160. package/dist/icons/generated/shard-00.cjs.map +1 -0
  161. package/dist/icons/generated/shard-00.js +48 -0
  162. package/dist/icons/generated/shard-00.js.map +1 -0
  163. package/dist/icons/generated/shard-01.cjs +2 -0
  164. package/dist/icons/generated/shard-01.cjs.map +1 -0
  165. package/dist/icons/generated/shard-01.js +48 -0
  166. package/dist/icons/generated/shard-01.js.map +1 -0
  167. package/dist/icons/generated/shard-02.cjs +2 -0
  168. package/dist/icons/generated/shard-02.cjs.map +1 -0
  169. package/dist/icons/generated/shard-02.js +48 -0
  170. package/dist/icons/generated/shard-02.js.map +1 -0
  171. package/dist/icons/generated/shard-03.cjs +2 -0
  172. package/dist/icons/generated/shard-03.cjs.map +1 -0
  173. package/dist/icons/generated/shard-03.js +48 -0
  174. package/dist/icons/generated/shard-03.js.map +1 -0
  175. package/dist/icons/generated/shard-04.cjs +2 -0
  176. package/dist/icons/generated/shard-04.cjs.map +1 -0
  177. package/dist/icons/generated/shard-04.js +48 -0
  178. package/dist/icons/generated/shard-04.js.map +1 -0
  179. package/dist/icons/generated/shard-05.cjs +2 -0
  180. package/dist/icons/generated/shard-05.cjs.map +1 -0
  181. package/dist/icons/generated/shard-05.js +48 -0
  182. package/dist/icons/generated/shard-05.js.map +1 -0
  183. package/dist/icons/generated/shard-06.cjs +2 -0
  184. package/dist/icons/generated/shard-06.cjs.map +1 -0
  185. package/dist/icons/generated/shard-06.js +48 -0
  186. package/dist/icons/generated/shard-06.js.map +1 -0
  187. package/dist/icons/generated/shard-07.cjs +2 -0
  188. package/dist/icons/generated/shard-07.cjs.map +1 -0
  189. package/dist/icons/generated/shard-07.js +48 -0
  190. package/dist/icons/generated/shard-07.js.map +1 -0
  191. package/dist/icons/generated/shard-08.cjs +2 -0
  192. package/dist/icons/generated/shard-08.cjs.map +1 -0
  193. package/dist/icons/generated/shard-08.js +48 -0
  194. package/dist/icons/generated/shard-08.js.map +1 -0
  195. package/dist/icons/generated/shard-09.cjs +2 -0
  196. package/dist/icons/generated/shard-09.cjs.map +1 -0
  197. package/dist/icons/generated/shard-09.js +48 -0
  198. package/dist/icons/generated/shard-09.js.map +1 -0
  199. package/dist/icons/generated/shard-10.cjs +2 -0
  200. package/dist/icons/generated/shard-10.cjs.map +1 -0
  201. package/dist/icons/generated/shard-10.js +48 -0
  202. package/dist/icons/generated/shard-10.js.map +1 -0
  203. package/dist/icons/generated/shard-11.cjs +2 -0
  204. package/dist/icons/generated/shard-11.cjs.map +1 -0
  205. package/dist/icons/generated/shard-11.js +48 -0
  206. package/dist/icons/generated/shard-11.js.map +1 -0
  207. package/dist/icons/generated/shard-12.cjs +2 -0
  208. package/dist/icons/generated/shard-12.cjs.map +1 -0
  209. package/dist/icons/generated/shard-12.js +48 -0
  210. package/dist/icons/generated/shard-12.js.map +1 -0
  211. package/dist/icons/generated/shard-13.cjs +2 -0
  212. package/dist/icons/generated/shard-13.cjs.map +1 -0
  213. package/dist/icons/generated/shard-13.js +48 -0
  214. package/dist/icons/generated/shard-13.js.map +1 -0
  215. package/dist/icons/generated/shard-14.cjs +2 -0
  216. package/dist/icons/generated/shard-14.cjs.map +1 -0
  217. package/dist/icons/generated/shard-14.js +48 -0
  218. package/dist/icons/generated/shard-14.js.map +1 -0
  219. package/dist/icons/generated/shard-15.cjs +2 -0
  220. package/dist/icons/generated/shard-15.cjs.map +1 -0
  221. package/dist/icons/generated/shard-15.js +48 -0
  222. package/dist/icons/generated/shard-15.js.map +1 -0
  223. package/dist/icons/generated/shard-16.cjs +2 -0
  224. package/dist/icons/generated/shard-16.cjs.map +1 -0
  225. package/dist/icons/generated/shard-16.js +48 -0
  226. package/dist/icons/generated/shard-16.js.map +1 -0
  227. package/dist/icons/generated/shard-17.cjs +2 -0
  228. package/dist/icons/generated/shard-17.cjs.map +1 -0
  229. package/dist/icons/generated/shard-17.js +48 -0
  230. package/dist/icons/generated/shard-17.js.map +1 -0
  231. package/dist/icons/generated/shard-18.cjs +2 -0
  232. package/dist/icons/generated/shard-18.cjs.map +1 -0
  233. package/dist/icons/generated/shard-18.js +48 -0
  234. package/dist/icons/generated/shard-18.js.map +1 -0
  235. package/dist/icons/generated/shard-19.cjs +2 -0
  236. package/dist/icons/generated/shard-19.cjs.map +1 -0
  237. package/dist/icons/generated/shard-19.js +48 -0
  238. package/dist/icons/generated/shard-19.js.map +1 -0
  239. package/dist/icons/generated/shard-20.cjs +2 -0
  240. package/dist/icons/generated/shard-20.cjs.map +1 -0
  241. package/dist/icons/generated/shard-20.js +48 -0
  242. package/dist/icons/generated/shard-20.js.map +1 -0
  243. package/dist/icons/generated/shard-21.cjs +2 -0
  244. package/dist/icons/generated/shard-21.cjs.map +1 -0
  245. package/dist/icons/generated/shard-21.js +48 -0
  246. package/dist/icons/generated/shard-21.js.map +1 -0
  247. package/dist/icons/generated/shard-22.cjs +2 -0
  248. package/dist/icons/generated/shard-22.cjs.map +1 -0
  249. package/dist/icons/generated/shard-22.js +48 -0
  250. package/dist/icons/generated/shard-22.js.map +1 -0
  251. package/dist/icons/generated/shard-23.cjs +2 -0
  252. package/dist/icons/generated/shard-23.cjs.map +1 -0
  253. package/dist/icons/generated/shard-23.js +48 -0
  254. package/dist/icons/generated/shard-23.js.map +1 -0
  255. package/dist/icons/generated/shard-24.cjs +2 -0
  256. package/dist/icons/generated/shard-24.cjs.map +1 -0
  257. package/dist/icons/generated/shard-24.js +48 -0
  258. package/dist/icons/generated/shard-24.js.map +1 -0
  259. package/dist/icons/generated/shard-25.cjs +2 -0
  260. package/dist/icons/generated/shard-25.cjs.map +1 -0
  261. package/dist/icons/generated/shard-25.js +48 -0
  262. package/dist/icons/generated/shard-25.js.map +1 -0
  263. package/dist/icons/generated/shard-26.cjs +2 -0
  264. package/dist/icons/generated/shard-26.cjs.map +1 -0
  265. package/dist/icons/generated/shard-26.js +48 -0
  266. package/dist/icons/generated/shard-26.js.map +1 -0
  267. package/dist/icons/generated/shard-27.cjs +2 -0
  268. package/dist/icons/generated/shard-27.cjs.map +1 -0
  269. package/dist/icons/generated/shard-27.js +48 -0
  270. package/dist/icons/generated/shard-27.js.map +1 -0
  271. package/dist/icons/generated/shard-28.cjs +2 -0
  272. package/dist/icons/generated/shard-28.cjs.map +1 -0
  273. package/dist/icons/generated/shard-28.js +48 -0
  274. package/dist/icons/generated/shard-28.js.map +1 -0
  275. package/dist/icons/generated/shard-29.cjs +2 -0
  276. package/dist/icons/generated/shard-29.cjs.map +1 -0
  277. package/dist/icons/generated/shard-29.js +48 -0
  278. package/dist/icons/generated/shard-29.js.map +1 -0
  279. package/dist/icons/generated/shard-30.cjs +2 -0
  280. package/dist/icons/generated/shard-30.cjs.map +1 -0
  281. package/dist/icons/generated/shard-30.js +48 -0
  282. package/dist/icons/generated/shard-30.js.map +1 -0
  283. package/dist/icons/generated/shard-31.cjs +2 -0
  284. package/dist/icons/generated/shard-31.cjs.map +1 -0
  285. package/dist/icons/generated/shard-31.js +48 -0
  286. package/dist/icons/generated/shard-31.js.map +1 -0
  287. package/dist/icons/generated/shard-32.cjs +2 -0
  288. package/dist/icons/generated/shard-32.cjs.map +1 -0
  289. package/dist/icons/generated/shard-32.js +48 -0
  290. package/dist/icons/generated/shard-32.js.map +1 -0
  291. package/dist/icons/generated/shard-33.cjs +2 -0
  292. package/dist/icons/generated/shard-33.cjs.map +1 -0
  293. package/dist/icons/generated/shard-33.js +48 -0
  294. package/dist/icons/generated/shard-33.js.map +1 -0
  295. package/dist/icons/generated/shard-34.cjs +2 -0
  296. package/dist/icons/generated/shard-34.cjs.map +1 -0
  297. package/dist/icons/generated/shard-34.js +48 -0
  298. package/dist/icons/generated/shard-34.js.map +1 -0
  299. package/dist/icons/generated/shard-35.cjs +2 -0
  300. package/dist/icons/generated/shard-35.cjs.map +1 -0
  301. package/dist/icons/generated/shard-35.js +48 -0
  302. package/dist/icons/generated/shard-35.js.map +1 -0
  303. package/dist/icons/generated/shard-36.cjs +2 -0
  304. package/dist/icons/generated/shard-36.cjs.map +1 -0
  305. package/dist/icons/generated/shard-36.js +48 -0
  306. package/dist/icons/generated/shard-36.js.map +1 -0
  307. package/dist/icons/generated/shard-37.cjs +2 -0
  308. package/dist/icons/generated/shard-37.cjs.map +1 -0
  309. package/dist/icons/generated/shard-37.js +48 -0
  310. package/dist/icons/generated/shard-37.js.map +1 -0
  311. package/dist/icons/generated/shard-38.cjs +2 -0
  312. package/dist/icons/generated/shard-38.cjs.map +1 -0
  313. package/dist/icons/generated/shard-38.js +48 -0
  314. package/dist/icons/generated/shard-38.js.map +1 -0
  315. package/dist/icons/generated/shard-39.cjs +2 -0
  316. package/dist/icons/generated/shard-39.cjs.map +1 -0
  317. package/dist/icons/generated/shard-39.js +48 -0
  318. package/dist/icons/generated/shard-39.js.map +1 -0
  319. package/dist/icons/generated/shard-40.cjs +2 -0
  320. package/dist/icons/generated/shard-40.cjs.map +1 -0
  321. package/dist/icons/generated/shard-40.js +48 -0
  322. package/dist/icons/generated/shard-40.js.map +1 -0
  323. package/dist/icons/generated/shard-41.cjs +2 -0
  324. package/dist/icons/generated/shard-41.cjs.map +1 -0
  325. package/dist/icons/generated/shard-41.js +48 -0
  326. package/dist/icons/generated/shard-41.js.map +1 -0
  327. package/dist/icons/generated/shard-42.cjs +2 -0
  328. package/dist/icons/generated/shard-42.cjs.map +1 -0
  329. package/dist/icons/generated/shard-42.js +48 -0
  330. package/dist/icons/generated/shard-42.js.map +1 -0
  331. package/dist/icons/generated/shard-43.cjs +2 -0
  332. package/dist/icons/generated/shard-43.cjs.map +1 -0
  333. package/dist/icons/generated/shard-43.js +48 -0
  334. package/dist/icons/generated/shard-43.js.map +1 -0
  335. package/dist/icons/generated/shard-44.cjs +2 -0
  336. package/dist/icons/generated/shard-44.cjs.map +1 -0
  337. package/dist/icons/generated/shard-44.js +15 -0
  338. package/dist/icons/generated/shard-44.js.map +1 -0
  339. package/dist/icons/material-symbols.cjs +1 -1
  340. package/dist/icons/material-symbols.cjs.map +1 -1
  341. package/dist/icons/material-symbols.js +240 -1
  342. package/dist/icons/material-symbols.js.map +1 -1
  343. package/dist/icons/normalize-icon-name.cjs +2 -0
  344. package/dist/icons/normalize-icon-name.cjs.map +1 -0
  345. package/dist/icons/normalize-icon-name.js +9 -0
  346. package/dist/icons/normalize-icon-name.js.map +1 -0
  347. package/dist/icons/shard-cache.cjs +1 -1
  348. package/dist/icons/shard-cache.cjs.map +1 -1
  349. package/dist/icons/shard-cache.js +85 -32
  350. package/dist/icons/shard-cache.js.map +1 -1
  351. package/dist/icons/validate-icon-name.cjs +2 -0
  352. package/dist/icons/validate-icon-name.cjs.map +1 -0
  353. package/dist/icons/validate-icon-name.js +11 -0
  354. package/dist/icons/validate-icon-name.js.map +1 -0
  355. package/dist/icons-virtual-id.d.ts +24 -0
  356. package/dist/icons-virtual.cjs +2 -0
  357. package/dist/icons-virtual.cjs.map +1 -0
  358. package/dist/icons-virtual.d.ts +30 -22
  359. package/dist/icons-virtual.js +6 -0
  360. package/dist/icons-virtual.js.map +1 -0
  361. package/dist/icons.cjs +1 -1
  362. package/dist/icons.d.ts +282 -33
  363. package/dist/icons.js +11 -7
  364. package/dist/offline/create-offline-sync.cjs +1 -1
  365. package/dist/offline/create-offline-sync.cjs.map +1 -1
  366. package/dist/offline/create-offline-sync.js +17 -9
  367. package/dist/offline/create-offline-sync.js.map +1 -1
  368. package/dist/offline/use-offline-sync.cjs +1 -1
  369. package/dist/offline/use-offline-sync.cjs.map +1 -1
  370. package/dist/offline/use-offline-sync.js +7 -8
  371. package/dist/offline/use-offline-sync.js.map +1 -1
  372. package/dist/push/use-push-subscription.cjs +1 -1
  373. package/dist/push/use-push-subscription.cjs.map +1 -1
  374. package/dist/push/use-push-subscription.js +13 -12
  375. package/dist/push/use-push-subscription.js.map +1 -1
  376. package/dist/query/retry-policy.cjs +1 -1
  377. package/dist/query/retry-policy.cjs.map +1 -1
  378. package/dist/query/retry-policy.js +3 -3
  379. package/dist/query/retry-policy.js.map +1 -1
  380. package/dist/sse/use-event-stream.cjs +1 -1
  381. package/dist/sse/use-event-stream.cjs.map +1 -1
  382. package/dist/sse/use-event-stream.js +19 -20
  383. package/dist/sse/use-event-stream.js.map +1 -1
  384. package/dist/styles.css +1 -1
  385. package/dist/tabular/use-tabular-predictor.cjs +1 -1
  386. package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
  387. package/dist/tabular/use-tabular-predictor.js +20 -17
  388. package/dist/tabular/use-tabular-predictor.js.map +1 -1
  389. package/dist/tempest-react-sdk.cjs +1 -1
  390. package/dist/tempest-react-sdk.d.ts +458 -213
  391. package/dist/tempest-react-sdk.js +328 -329
  392. package/dist/theme/ThemeProvider.cjs +1 -1
  393. package/dist/theme/ThemeProvider.cjs.map +1 -1
  394. package/dist/theme/ThemeProvider.js +12 -17
  395. package/dist/theme/ThemeProvider.js.map +1 -1
  396. package/dist/utils/base64.cjs +2 -0
  397. package/dist/utils/base64.cjs.map +1 -0
  398. package/dist/utils/base64.js +16 -0
  399. package/dist/utils/base64.js.map +1 -0
  400. package/dist/utils/compare-values.cjs +1 -1
  401. package/dist/utils/compare-values.cjs.map +1 -1
  402. package/dist/utils/compare-values.js +4 -3
  403. package/dist/utils/compare-values.js.map +1 -1
  404. package/dist/utils/compressed-storage.cjs +1 -1
  405. package/dist/utils/compressed-storage.cjs.map +1 -1
  406. package/dist/utils/compressed-storage.js +16 -46
  407. package/dist/utils/compressed-storage.js.map +1 -1
  408. package/dist/utils/dev-mode.cjs.map +1 -1
  409. package/dist/utils/dev-mode.js.map +1 -1
  410. package/dist/utils/storage.cjs +1 -1
  411. package/dist/utils/storage.cjs.map +1 -1
  412. package/dist/utils/storage.js +37 -17
  413. package/dist/utils/storage.js.map +1 -1
  414. package/dist/vision/use-camera-stream.cjs +1 -1
  415. package/dist/vision/use-camera-stream.cjs.map +1 -1
  416. package/dist/vision/use-camera-stream.js +34 -33
  417. package/dist/vision/use-camera-stream.js.map +1 -1
  418. package/dist/vite/base-url.cjs +2 -0
  419. package/dist/vite/base-url.cjs.map +1 -0
  420. package/dist/vite/base-url.js +8 -0
  421. package/dist/vite/base-url.js.map +1 -0
  422. package/dist/vite/tempest-icons.cjs +4 -4
  423. package/dist/vite/tempest-icons.cjs.map +1 -1
  424. package/dist/vite/tempest-icons.js +26 -26
  425. package/dist/vite/tempest-icons.js.map +1 -1
  426. package/dist/vite/tempest-pwa-dev-sw.cjs +1 -1
  427. package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
  428. package/dist/vite/tempest-pwa-dev-sw.js +54 -29
  429. package/dist/vite/tempest-pwa-dev-sw.js.map +1 -1
  430. package/dist/vite/tempest-pwa-manifest.cjs +2 -2
  431. package/dist/vite/tempest-pwa-manifest.cjs.map +1 -1
  432. package/dist/vite/tempest-pwa-manifest.js +15 -14
  433. package/dist/vite/tempest-pwa-manifest.js.map +1 -1
  434. package/dist/vite.d.ts +3 -3
  435. package/dist/ws/use-web-socket.cjs +1 -1
  436. package/dist/ws/use-web-socket.cjs.map +1 -1
  437. package/dist/ws/use-web-socket.js +40 -42
  438. package/dist/ws/use-web-socket.js.map +1 -1
  439. package/package.json +5 -2
  440. package/dist/icons/generated/shard-a.cjs +0 -2
  441. package/dist/icons/generated/shard-a.cjs.map +0 -1
  442. package/dist/icons/generated/shard-a.js +0 -114
  443. package/dist/icons/generated/shard-a.js.map +0 -1
  444. package/dist/icons/generated/shard-b.cjs +0 -2
  445. package/dist/icons/generated/shard-b.cjs.map +0 -1
  446. package/dist/icons/generated/shard-b.js +0 -158
  447. package/dist/icons/generated/shard-b.js.map +0 -1
  448. package/dist/icons/generated/shard-c.cjs +0 -2
  449. package/dist/icons/generated/shard-c.cjs.map +0 -1
  450. package/dist/icons/generated/shard-c.js +0 -269
  451. package/dist/icons/generated/shard-c.js.map +0 -1
  452. package/dist/icons/generated/shard-d.cjs +0 -2
  453. package/dist/icons/generated/shard-d.cjs.map +0 -1
  454. package/dist/icons/generated/shard-d.js +0 -62
  455. package/dist/icons/generated/shard-d.js.map +0 -1
  456. package/dist/icons/generated/shard-e.cjs +0 -2
  457. package/dist/icons/generated/shard-e.cjs.map +0 -1
  458. package/dist/icons/generated/shard-e.js +0 -33
  459. package/dist/icons/generated/shard-e.js.map +0 -1
  460. package/dist/icons/generated/shard-f.cjs +0 -2
  461. package/dist/icons/generated/shard-f.cjs.map +0 -1
  462. package/dist/icons/generated/shard-f.js +0 -145
  463. package/dist/icons/generated/shard-f.js.map +0 -1
  464. package/dist/icons/generated/shard-g.cjs +0 -2
  465. package/dist/icons/generated/shard-g.cjs.map +0 -1
  466. package/dist/icons/generated/shard-g.js +0 -61
  467. package/dist/icons/generated/shard-g.js.map +0 -1
  468. package/dist/icons/generated/shard-h.cjs +0 -2
  469. package/dist/icons/generated/shard-h.cjs.map +0 -1
  470. package/dist/icons/generated/shard-h.js +0 -62
  471. package/dist/icons/generated/shard-h.js.map +0 -1
  472. package/dist/icons/generated/shard-i.cjs +0 -2
  473. package/dist/icons/generated/shard-i.cjs.map +0 -1
  474. package/dist/icons/generated/shard-i.js +0 -30
  475. package/dist/icons/generated/shard-i.js.map +0 -1
  476. package/dist/icons/generated/shard-j.cjs +0 -2
  477. package/dist/icons/generated/shard-j.cjs.map +0 -1
  478. package/dist/icons/generated/shard-j.js +0 -10
  479. package/dist/icons/generated/shard-j.js.map +0 -1
  480. package/dist/icons/generated/shard-k.cjs +0 -2
  481. package/dist/icons/generated/shard-k.cjs.map +0 -1
  482. package/dist/icons/generated/shard-k.js +0 -16
  483. package/dist/icons/generated/shard-k.js.map +0 -1
  484. package/dist/icons/generated/shard-l.cjs +0 -2
  485. package/dist/icons/generated/shard-l.cjs.map +0 -1
  486. package/dist/icons/generated/shard-l.js +0 -92
  487. package/dist/icons/generated/shard-l.js.map +0 -1
  488. package/dist/icons/generated/shard-m.cjs +0 -2
  489. package/dist/icons/generated/shard-m.cjs.map +0 -1
  490. package/dist/icons/generated/shard-m.js +0 -143
  491. package/dist/icons/generated/shard-m.js.map +0 -1
  492. package/dist/icons/generated/shard-n.cjs +0 -2
  493. package/dist/icons/generated/shard-n.cjs.map +0 -1
  494. package/dist/icons/generated/shard-n.js +0 -24
  495. package/dist/icons/generated/shard-n.js.map +0 -1
  496. package/dist/icons/generated/shard-o.cjs +0 -2
  497. package/dist/icons/generated/shard-o.cjs.map +0 -1
  498. package/dist/icons/generated/shard-o.js +0 -17
  499. package/dist/icons/generated/shard-o.js.map +0 -1
  500. package/dist/icons/generated/shard-p.cjs +0 -2
  501. package/dist/icons/generated/shard-p.cjs.map +0 -1
  502. package/dist/icons/generated/shard-p.js +0 -114
  503. package/dist/icons/generated/shard-p.js.map +0 -1
  504. package/dist/icons/generated/shard-q.cjs +0 -2
  505. package/dist/icons/generated/shard-q.cjs.map +0 -1
  506. package/dist/icons/generated/shard-q.js +0 -10
  507. package/dist/icons/generated/shard-q.js.map +0 -1
  508. package/dist/icons/generated/shard-r.cjs +0 -2
  509. package/dist/icons/generated/shard-r.cjs.map +0 -1
  510. package/dist/icons/generated/shard-r.js +0 -79
  511. package/dist/icons/generated/shard-r.js.map +0 -1
  512. package/dist/icons/generated/shard-s.cjs +0 -2
  513. package/dist/icons/generated/shard-s.cjs.map +0 -1
  514. package/dist/icons/generated/shard-s.js +0 -256
  515. package/dist/icons/generated/shard-s.js.map +0 -1
  516. package/dist/icons/generated/shard-t.cjs +0 -2
  517. package/dist/icons/generated/shard-t.cjs.map +0 -1
  518. package/dist/icons/generated/shard-t.js +0 -109
  519. package/dist/icons/generated/shard-t.js.map +0 -1
  520. package/dist/icons/generated/shard-u.cjs +0 -2
  521. package/dist/icons/generated/shard-u.cjs.map +0 -1
  522. package/dist/icons/generated/shard-u.js +0 -50
  523. package/dist/icons/generated/shard-u.js.map +0 -1
  524. package/dist/icons/generated/shard-v.cjs +0 -2
  525. package/dist/icons/generated/shard-v.cjs.map +0 -1
  526. package/dist/icons/generated/shard-v.js +0 -30
  527. package/dist/icons/generated/shard-v.js.map +0 -1
  528. package/dist/icons/generated/shard-w.cjs +0 -2
  529. package/dist/icons/generated/shard-w.cjs.map +0 -1
  530. package/dist/icons/generated/shard-w.js +0 -48
  531. package/dist/icons/generated/shard-w.js.map +0 -1
  532. package/dist/icons/generated/shard-x.cjs +0 -2
  533. package/dist/icons/generated/shard-x.cjs.map +0 -1
  534. package/dist/icons/generated/shard-x.js +0 -10
  535. package/dist/icons/generated/shard-x.js.map +0 -1
  536. package/dist/icons/generated/shard-z.cjs +0 -2
  537. package/dist/icons/generated/shard-z.cjs.map +0 -1
  538. package/dist/icons/generated/shard-z.js +0 -25
  539. package/dist/icons/generated/shard-z.js.map +0 -1
@@ -1,10 +1,11 @@
1
+ import { base64ToBytes as e, bytesToBase64 as t } from "../utils/base64.js";
1
2
  //#region src/auth/passkey.ts
2
- var e = class extends Error {
3
+ var n = class extends Error {
3
4
  kind;
4
5
  constructor(e, t, n) {
5
6
  super(t), this.name = "PasskeyError", this.kind = e, this.cause = n;
6
7
  }
7
- }, t = [
8
+ }, r = [
8
9
  {
9
10
  type: "public-key",
10
11
  alg: -8
@@ -18,24 +19,21 @@ var e = class extends Error {
18
19
  alg: -257
19
20
  }
20
21
  ];
21
- function n() {
22
+ function i() {
22
23
  return globalThis.PublicKeyCredential;
23
24
  }
24
- function r(e) {
25
- let t = e.replace(/-/g, "+").replace(/_/g, "/"), n = t.padEnd(t.length + (4 - t.length % 4) % 4, "="), r = atob(n), i = new Uint8Array(r.length);
26
- for (let e = 0; e < r.length; e += 1) i[e] = r.charCodeAt(e);
27
- return i;
25
+ function a(t) {
26
+ return e(t);
28
27
  }
29
- function i(e) {
30
- let t = e instanceof Uint8Array ? e : new Uint8Array(e), n = "";
31
- for (let e of t) n += String.fromCharCode(e);
32
- return btoa(n).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
28
+ function o(e) {
29
+ let n = e instanceof Uint8Array ? e : new Uint8Array(e);
30
+ return t(n, { urlSafe: !0 });
33
31
  }
34
- function a() {
35
- return typeof window < "u" && typeof navigator < "u" && navigator.credentials !== void 0 && typeof navigator.credentials.create == "function" && n() !== void 0;
32
+ function s() {
33
+ return typeof window < "u" && typeof navigator < "u" && navigator.credentials !== void 0 && typeof navigator.credentials.create == "function" && i() !== void 0;
36
34
  }
37
- async function o() {
38
- let e = n();
35
+ async function c() {
36
+ let e = i();
39
37
  if (!e?.isUserVerifyingPlatformAuthenticatorAvailable) return !1;
40
38
  try {
41
39
  return await e.isUserVerifyingPlatformAuthenticatorAvailable();
@@ -43,8 +41,8 @@ async function o() {
43
41
  return !1;
44
42
  }
45
43
  }
46
- async function s() {
47
- let e = n();
44
+ async function l() {
45
+ let e = i();
48
46
  if (!e?.isConditionalMediationAvailable) return !1;
49
47
  try {
50
48
  return await e.isConditionalMediationAvailable();
@@ -52,107 +50,107 @@ async function s() {
52
50
  return !1;
53
51
  }
54
52
  }
55
- function c(t, n) {
56
- if (t instanceof e) return t;
57
- if (typeof window < "u" && !window.isSecureContext) return new e("insecure", "Passkeys require a secure (HTTPS) connection.", t);
58
- if (t instanceof DOMException) switch (t.name) {
59
- case "NotAllowedError": return new e("cancelled", "The passkey prompt was dismissed or timed out. The browser does not say which — it must not reveal whether a credential exists.", t);
60
- case "InvalidStateError": return new e("already-registered", "This device already has a passkey for this account. Sign in with it instead of creating another.", t);
61
- case "NotSupportedError": return new e("not-supported", "No authenticator here supports the requested algorithms. Check the server's pubKeyCredParams.", t);
62
- case "SecurityError": return new e("rp-mismatch", "The relying-party id does not match this origin. rp.id must be the page's domain or a registrable parent of it.", t);
63
- case "AbortError": return new e("aborted", "The passkey request was aborted.", t);
53
+ function u(e, t) {
54
+ if (e instanceof n) return e;
55
+ if (typeof window < "u" && !window.isSecureContext) return new n("insecure", "Passkeys require a secure (HTTPS) connection.", e);
56
+ if (e instanceof DOMException) switch (e.name) {
57
+ case "NotAllowedError": return new n("cancelled", "The passkey prompt was dismissed or timed out. The browser does not say which — it must not reveal whether a credential exists.", e);
58
+ case "InvalidStateError": return new n("already-registered", "This device already has a passkey for this account. Sign in with it instead of creating another.", e);
59
+ case "NotSupportedError": return new n("not-supported", "No authenticator here supports the requested algorithms. Check the server's pubKeyCredParams.", e);
60
+ case "SecurityError": return new n("rp-mismatch", "The relying-party id does not match this origin. rp.id must be the page's domain or a registrable parent of it.", e);
61
+ case "AbortError": return new n("aborted", "The passkey request was aborted.", e);
64
62
  }
65
- return t instanceof TypeError ? new e("invalid-options", `The ${n} options the server sent are malformed. Check that challenge, user.id and credential ids are base64url.`, t) : new e("unknown", t instanceof Error ? t.message : `Unexpected error during the passkey ${n} ceremony.`, t);
63
+ return e instanceof TypeError ? new n("invalid-options", `The ${t} options the server sent are malformed. Check that challenge, user.id and credential ids are base64url.`, e) : new n("unknown", e instanceof Error ? e.message : `Unexpected error during the passkey ${t} ceremony.`, e);
66
64
  }
67
- function l(e) {
65
+ function d(e) {
68
66
  if (e) return e.map((e) => ({
69
- id: r(e.id),
67
+ id: a(e.id),
70
68
  type: e.type,
71
69
  transports: e.transports
72
70
  }));
73
71
  }
74
- function u(n = {}) {
75
- let { rpId: u, timeoutMs: d = 6e4, credentials: f } = n;
72
+ function f(e = {}) {
73
+ let { rpId: t, timeoutMs: i = 6e4, credentials: f } = e;
76
74
  function p() {
77
75
  if (f) return f;
78
- if (!a()) throw new e("unsupported", typeof window < "u" && !window.isSecureContext ? "Passkeys require a secure (HTTPS) connection." : "This browser does not support passkeys (WebAuthn).");
76
+ if (!s()) throw new n("unsupported", typeof window < "u" && !window.isSecureContext ? "Passkeys require a secure (HTTPS) connection." : "This browser does not support passkeys (WebAuthn).");
79
77
  return navigator.credentials;
80
78
  }
81
- async function m(n, a = {}) {
82
- let o = p(), s = {
83
- challenge: r(n.challenge),
79
+ async function m(e, s = {}) {
80
+ let c = p(), l = {
81
+ challenge: a(e.challenge),
84
82
  rp: {
85
- name: n.rp.name,
86
- id: n.rp.id ?? u
83
+ name: e.rp.name,
84
+ id: e.rp.id ?? t
87
85
  },
88
86
  user: {
89
- id: r(n.user.id),
90
- name: n.user.name,
91
- displayName: n.user.displayName
87
+ id: a(e.user.id),
88
+ name: e.user.name,
89
+ displayName: e.user.displayName
92
90
  },
93
- pubKeyCredParams: n.pubKeyCredParams ?? t,
94
- timeout: n.timeout ?? d,
95
- excludeCredentials: l(n.excludeCredentials),
96
- authenticatorSelection: n.authenticatorSelection,
97
- attestation: n.attestation,
98
- extensions: n.extensions
91
+ pubKeyCredParams: e.pubKeyCredParams ?? r,
92
+ timeout: e.timeout ?? i,
93
+ excludeCredentials: d(e.excludeCredentials),
94
+ authenticatorSelection: e.authenticatorSelection,
95
+ attestation: e.attestation,
96
+ extensions: e.extensions
99
97
  }, f;
100
98
  try {
101
- f = await o.create({
102
- publicKey: s,
103
- signal: a.signal
99
+ f = await c.create({
100
+ publicKey: l,
101
+ signal: s.signal
104
102
  });
105
103
  } catch (e) {
106
- throw c(e, "register");
104
+ throw u(e, "register");
107
105
  }
108
- if (!f) throw new e("unknown", "The authenticator returned no credential.");
106
+ if (!f) throw new n("unknown", "The authenticator returned no credential.");
109
107
  let m = f, h = m.response, g = h.getPublicKey?.();
110
108
  return {
111
109
  id: m.id,
112
- rawId: i(m.rawId),
110
+ rawId: o(m.rawId),
113
111
  type: "public-key",
114
112
  authenticatorAttachment: m.authenticatorAttachment ?? null,
115
113
  response: {
116
- clientDataJSON: i(h.clientDataJSON),
117
- attestationObject: i(h.attestationObject),
114
+ clientDataJSON: o(h.clientDataJSON),
115
+ attestationObject: o(h.attestationObject),
118
116
  transports: h.getTransports?.(),
119
117
  publicKeyAlgorithm: h.getPublicKeyAlgorithm?.(),
120
- publicKey: g ? i(g) : void 0,
121
- authenticatorData: h.getAuthenticatorData ? i(h.getAuthenticatorData()) : void 0
118
+ publicKey: g ? o(g) : void 0,
119
+ authenticatorData: h.getAuthenticatorData ? o(h.getAuthenticatorData()) : void 0
122
120
  },
123
121
  clientExtensionResults: m.getClientExtensionResults()
124
122
  };
125
123
  }
126
- async function h(t, n = {}) {
127
- let a = p(), o = {
128
- challenge: r(t.challenge),
129
- rpId: t.rpId ?? u,
130
- timeout: t.timeout ?? d,
131
- allowCredentials: l(t.allowCredentials),
132
- userVerification: t.userVerification,
133
- extensions: t.extensions
134
- }, s;
124
+ async function h(e, r = {}) {
125
+ let s = p(), c = {
126
+ challenge: a(e.challenge),
127
+ rpId: e.rpId ?? t,
128
+ timeout: e.timeout ?? i,
129
+ allowCredentials: d(e.allowCredentials),
130
+ userVerification: e.userVerification,
131
+ extensions: e.extensions
132
+ }, l;
135
133
  try {
136
- s = await a.get({
137
- publicKey: o,
138
- signal: n.signal,
139
- mediation: n.mediation
134
+ l = await s.get({
135
+ publicKey: c,
136
+ signal: r.signal,
137
+ mediation: r.mediation
140
138
  });
141
139
  } catch (e) {
142
- throw c(e, "authenticate");
140
+ throw u(e, "authenticate");
143
141
  }
144
- if (!s) throw new e("unknown", "The authenticator returned no credential.");
145
- let f = s, m = f.response;
142
+ if (!l) throw new n("unknown", "The authenticator returned no credential.");
143
+ let f = l, m = f.response;
146
144
  return {
147
145
  id: f.id,
148
- rawId: i(f.rawId),
146
+ rawId: o(f.rawId),
149
147
  type: "public-key",
150
148
  authenticatorAttachment: f.authenticatorAttachment ?? null,
151
149
  response: {
152
- clientDataJSON: i(m.clientDataJSON),
153
- authenticatorData: i(m.authenticatorData),
154
- signature: i(m.signature),
155
- userHandle: m.userHandle ? i(m.userHandle) : null
150
+ clientDataJSON: o(m.clientDataJSON),
151
+ authenticatorData: o(m.authenticatorData),
152
+ signature: o(m.signature),
153
+ userHandle: m.userHandle ? o(m.userHandle) : null
156
154
  },
157
155
  clientExtensionResults: f.getClientExtensionResults()
158
156
  };
@@ -160,12 +158,12 @@ function u(n = {}) {
160
158
  return {
161
159
  register: m,
162
160
  authenticate: h,
163
- isSupported: () => f !== void 0 || a(),
164
- isPlatformAuthenticatorAvailable: o,
165
- isConditionalMediationAvailable: s
161
+ isSupported: () => f !== void 0 || s(),
162
+ isPlatformAuthenticatorAvailable: c,
163
+ isConditionalMediationAvailable: l
166
164
  };
167
165
  }
168
166
  //#endregion
169
- export { t as DEFAULT_PUB_KEY_CRED_PARAMS, e as PasskeyError, r as base64UrlToBytes, i as bytesToBase64Url, c as classifyPasskeyError, u as createPasskeyClient, s as isConditionalMediationAvailable, a as isPasskeySupported, o as isPlatformAuthenticatorAvailable };
167
+ export { r as DEFAULT_PUB_KEY_CRED_PARAMS, n as PasskeyError, a as base64UrlToBytes, o as bytesToBase64Url, u as classifyPasskeyError, f as createPasskeyClient, l as isConditionalMediationAvailable, s as isPasskeySupported, c as isPlatformAuthenticatorAvailable };
170
168
 
171
169
  //# sourceMappingURL=passkey.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"passkey.js","names":[],"sources":["../../src/auth/passkey.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines, function-lines — the WebAuthn client half: the JSON\n * shapes both ceremonies exchange with a backend, base64url ↔ ArrayBuffer, the\n * capability probes and the error classifier. The two ceremonies are near-mirrors\n * that must not drift — register and authenticate encode the same credential fields\n * in the same order — and the file's docstring is also the specification of the four\n * backend routes it expects.\n */\n/**\n * Classified reason a passkey ceremony did not produce a credential.\n *\n * The kinds group the raw `DOMException.name` values the way a UI has to branch\n * on them, which is *not* how the spec groups them:\n *\n * - `\"cancelled\"` covers `NotAllowedError`, which the browser raises both when\n * the user dismissed the sheet and when the ceremony timed out. They are\n * indistinguishable **by design** — telling a site \"the user has no credential\n * for you\" would leak account existence — so a UI must treat them as one thing.\n * - `\"already-registered\"` (`InvalidStateError`) is not really a failure: this\n * device already holds a credential for this user. The correct reaction is\n * \"you are already set up on this device\", never a red error.\n * - `\"rp-mismatch\"` (`SecurityError`) is the single most common integration bug:\n * `rp.id` must equal the page's domain or a registrable parent of it.\n */\nexport type PasskeyErrorKind =\n | \"unsupported\"\n | \"insecure\"\n | \"cancelled\"\n | \"already-registered\"\n | \"not-supported\"\n | \"rp-mismatch\"\n | \"invalid-options\"\n | \"aborted\"\n | \"unknown\";\n\n/** Which ceremony was running, so the message can name it. */\nexport type PasskeyCeremony = \"register\" | \"authenticate\";\n\n/**\n * A passkey failure carrying a stable {@link PasskeyErrorKind} plus an English\n * message safe to show a user.\n *\n * A class rather than the plain `{ kind, message }` object the media classifier\n * returns, because these surface by rejecting a promise: an `Error` subclass keeps\n * stack traces, `instanceof` checks and logging intact, and `kind` is what code\n * branches on.\n */\nexport class PasskeyError extends Error {\n /** Stable, branchable classification. */\n readonly kind: PasskeyErrorKind;\n\n /**\n * Build a classified passkey error.\n *\n * @param kind - The classification a UI branches on.\n * @param message - English, user-safe explanation.\n * @param cause - The original thrown value, when there was one.\n */\n constructor(kind: PasskeyErrorKind, message: string, cause?: unknown) {\n super(message);\n this.name = \"PasskeyError\";\n this.kind = kind;\n this.cause = cause;\n }\n}\n\n/**\n * Minimal subset of `navigator.credentials` the passkey client touches.\n *\n * Declared here — the `<X>Like` pattern the SDK's adapters use — for two reasons:\n * jsdom has no `navigator.credentials` at all, so tests must inject a double; and\n * `mediation: \"conditional\"` is newer than some TypeScript DOM libs, which would\n * otherwise reject the call that makes autofill work.\n */\nexport interface CredentialsContainerLike {\n /** Runs the registration ceremony. */\n create(options: {\n publicKey: PublicKeyCredentialCreationOptions;\n signal?: AbortSignal;\n }): Promise<Credential | null>;\n /** Runs the authentication ceremony. */\n get(options: {\n publicKey: PublicKeyCredentialRequestOptions;\n signal?: AbortSignal;\n mediation?: string;\n }): Promise<Credential | null>;\n}\n\n/** How the browser should surface the authentication ceremony. */\nexport type PasskeyMediation = \"optional\" | \"conditional\" | \"required\" | \"silent\";\n\n/**\n * Server-issued registration options, in the base64url JSON shape every WebAuthn\n * backend speaks (`PublicKeyCredentialCreationOptionsJSON` in the spec).\n *\n * `challenge`, `user.id` and every `excludeCredentials[].id` are **base64url**\n * strings here and `ArrayBuffer`s in the DOM API. Converting them is the plumbing\n * this client owns.\n */\nexport interface PasskeyCreationOptionsJSON {\n /** Base64url server challenge. Single-use; the server must remember it. */\n challenge: string;\n /** Relying party. `id` defaults to the client's `rpId`, then to the origin. */\n rp: { name: string; id?: string };\n /** The account. `id` is base64url of an opaque, stable user handle. */\n user: { id: string; name: string; displayName: string };\n /** Allowed COSE algorithms. Defaults to {@link DEFAULT_PUB_KEY_CRED_PARAMS}. */\n pubKeyCredParams?: { type: \"public-key\"; alg: number }[];\n /** Ceremony timeout in ms. Defaults to the client's `timeoutMs`. */\n timeout?: number;\n /** Credentials this user already has, so the authenticator refuses a duplicate. */\n excludeCredentials?: { id: string; type: \"public-key\"; transports?: string[] }[];\n /** Resident-key / user-verification / attachment requirements. */\n authenticatorSelection?: AuthenticatorSelectionCriteria;\n /** Attestation conveyance. Leave unset (`\"none\"`) unless you verify it. */\n attestation?: AttestationConveyancePreference;\n /** Client extension inputs (`credProps`, `largeBlob`, …). */\n extensions?: AuthenticationExtensionsClientInputs;\n}\n\n/** Server-issued authentication options, base64url JSON. */\nexport interface PasskeyRequestOptionsJSON {\n /** Base64url server challenge. */\n challenge: string;\n /** Relying party id. Defaults to the client's `rpId`, then to the origin. */\n rpId?: string;\n /** Ceremony timeout in ms. Defaults to the client's `timeoutMs`. */\n timeout?: number;\n /** Restrict to these credentials. **Omit it** for usernameless / autofill flows. */\n allowCredentials?: { id: string; type: \"public-key\"; transports?: string[] }[];\n /** Whether the authenticator must verify the user (biometric / PIN). */\n userVerification?: UserVerificationRequirement;\n /** Client extension inputs. */\n extensions?: AuthenticationExtensionsClientInputs;\n}\n\n/** What the client sends to the backend to finish registration. */\nexport interface PasskeyRegistrationJSON {\n /** Base64url credential id. */\n id: string;\n /** Same bytes as `id`; both are sent because servers differ on which they read. */\n rawId: string;\n type: \"public-key\";\n /** `\"platform\"` (this device) or `\"cross-platform\"` (a phone or key). */\n authenticatorAttachment: string | null;\n response: {\n /** Base64url client data — the server re-checks challenge, origin and type. */\n clientDataJSON: string;\n /** Base64url attestation object, holding the new public key. */\n attestationObject: string;\n /** Transports the authenticator advertises, when the browser exposes them. */\n transports?: string[];\n /** COSE algorithm of the new key, when the browser exposes it. */\n publicKeyAlgorithm?: number;\n /** Base64url SPKI public key, when the browser exposes it. */\n publicKey?: string;\n /** Base64url authenticator data, when the browser exposes it. */\n authenticatorData?: string;\n };\n /** Extension outputs — `credProps.rk` tells you whether it is discoverable. */\n clientExtensionResults: AuthenticationExtensionsClientOutputs;\n}\n\n/** What the client sends to the backend to finish authentication. */\nexport interface PasskeyAuthenticationJSON {\n /** Base64url credential id — the server looks up the stored public key by it. */\n id: string;\n /** Same bytes as `id`. */\n rawId: string;\n type: \"public-key\";\n /** `\"platform\"` or `\"cross-platform\"`. */\n authenticatorAttachment: string | null;\n response: {\n /** Base64url client data. */\n clientDataJSON: string;\n /** Base64url authenticator data, carrying the signature counter. */\n authenticatorData: string;\n /** Base64url signature over `authenticatorData || sha256(clientDataJSON)`. */\n signature: string;\n /** Base64url user handle — present on discoverable credentials, else null. */\n userHandle: string | null;\n };\n /** Extension outputs. */\n clientExtensionResults: AuthenticationExtensionsClientOutputs;\n}\n\n/** Per-call knobs for {@link PasskeyClient.register}. */\nexport interface PasskeyRegisterInit {\n /** Cancel the ceremony (closes the browser sheet). */\n signal?: AbortSignal;\n}\n\n/** Per-call knobs for {@link PasskeyClient.authenticate}. */\nexport interface PasskeyAuthenticateInit extends PasskeyRegisterInit {\n /**\n * `\"conditional\"` is the autofill flow: no modal, the browser offers passkeys\n * inside a field marked `autocomplete=\"webauthn\"`. Requires a `signal`, and\n * only one conditional request may be live per page.\n */\n mediation?: PasskeyMediation;\n}\n\n/** Framework-free WebAuthn client. Build one with {@link createPasskeyClient}. */\nexport interface PasskeyClient {\n /** Run the registration ceremony and return the JSON your backend verifies. */\n register(\n options: PasskeyCreationOptionsJSON,\n init?: PasskeyRegisterInit,\n ): Promise<PasskeyRegistrationJSON>;\n /** Run the authentication ceremony and return the JSON your backend verifies. */\n authenticate(\n options: PasskeyRequestOptionsJSON,\n init?: PasskeyAuthenticateInit,\n ): Promise<PasskeyAuthenticationJSON>;\n /**\n * Whether this client can run a ceremony at all — the WebAuthn API exists, or a\n * `credentials` container was injected.\n */\n isSupported(): boolean;\n /** Whether this device has a built-in authenticator (Face ID, Hello, …). */\n isPlatformAuthenticatorAvailable(): Promise<boolean>;\n /** Whether autofill-driven (`\"conditional\"`) requests are available. */\n isConditionalMediationAvailable(): Promise<boolean>;\n}\n\n/** Options for {@link createPasskeyClient}. */\nexport interface CreatePasskeyClientOptions {\n /**\n * Default relying-party id, applied when the server options omit one. Must be\n * the page's domain or a registrable parent of it (`app.acme.com` may use\n * `acme.com`, never the other way round).\n */\n rpId?: string;\n /** Default ceremony timeout in ms. Default `60_000`. */\n timeoutMs?: number;\n /** `navigator.credentials` replacement, for tests. */\n credentials?: CredentialsContainerLike;\n}\n\n/**\n * COSE algorithms offered when the server sends no `pubKeyCredParams`, in\n * preference order.\n *\n * `-8` is Ed25519, which modern authenticators prefer and which produces the\n * smallest signatures. `-7` is ES256, the one algorithm every WebAuthn\n * authenticator supports. `-257` is RS256, needed for TPM-backed Windows Hello.\n * Offering all three is what avoids a `NotSupportedError` on some device you do\n * not own; a server that cannot verify one of them should send its own list.\n */\nexport const DEFAULT_PUB_KEY_CRED_PARAMS: { type: \"public-key\"; alg: number }[] = [\n { type: \"public-key\", alg: -8 },\n { type: \"public-key\", alg: -7 },\n { type: \"public-key\", alg: -257 },\n];\n\n/** Static members of `PublicKeyCredential` that are not in every DOM lib yet. */\ninterface PublicKeyCredentialStatics {\n isUserVerifyingPlatformAuthenticatorAvailable?: () => Promise<boolean>;\n isConditionalMediationAvailable?: () => Promise<boolean>;\n}\n\n/** The browser-supplied extras on an attestation response, all optional. */\ninterface AttestationExtras {\n getTransports?: () => string[];\n getPublicKey?: () => ArrayBuffer | null;\n getPublicKeyAlgorithm?: () => number;\n getAuthenticatorData?: () => ArrayBuffer;\n}\n\nfunction publicKeyCredentialStatics(): PublicKeyCredentialStatics | undefined {\n return (globalThis as { PublicKeyCredential?: PublicKeyCredentialStatics }).PublicKeyCredential;\n}\n\n/**\n * Decode a base64url string into bytes.\n *\n * WebAuthn transports every binary field as base64url (`-`/`_`, no padding)\n * because that is what survives JSON, while the DOM API insists on\n * `ArrayBuffer`. Getting this pair wrong — usually by feeding plain base64 to\n * `atob` and losing the last byte — is the classic broken-WebAuthn bug, which is\n * why the SDK owns it instead of leaving it to each app.\n *\n * @param value - Base64url text, with or without `=` padding.\n * @returns The decoded bytes.\n */\nexport function base64UrlToBytes(value: string): Uint8Array<ArrayBuffer> {\n const base64 = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\");\n const binary = atob(padded);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n}\n\n/**\n * Encode bytes as an unpadded base64url string.\n *\n * @param value - Bytes to encode, as a view or a raw buffer.\n * @returns Base64url text, safe to put in JSON and in a URL.\n */\nexport function bytesToBase64Url(value: ArrayBuffer | Uint8Array): string {\n const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/**\n * Whether this browser exposes WebAuthn at all.\n *\n * Note that \"supported\" is not \"usable\": WebAuthn also requires a secure context,\n * and a device may have no authenticator. Use\n * {@link isPlatformAuthenticatorAvailable} before offering a passkey button.\n */\nexport function isPasskeySupported(): boolean {\n return (\n typeof window !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n navigator.credentials !== undefined &&\n typeof navigator.credentials.create === \"function\" &&\n publicKeyCredentialStatics() !== undefined\n );\n}\n\n/**\n * Whether the device has a **built-in** authenticator — Face ID, Touch ID,\n * Windows Hello, an Android screen lock.\n *\n * This is the check that decides whether \"Entrar com passkey\" may be shown at\n * all. `isPasskeySupported()` is true on a desktop with no biometrics and no\n * security key, and offering a passkey there sends the user into a sheet that can\n * only be cancelled. A `false` here does not forbid passkeys — a phone can still\n * be used over hybrid/QR — it means the flow needs a second step, so present it\n * as \"usar meu celular\", not as one tap.\n *\n * @returns `false` when the API is missing, so a caller never has to null-check.\n */\nexport async function isPlatformAuthenticatorAvailable(): Promise<boolean> {\n const statics = publicKeyCredentialStatics();\n if (!statics?.isUserVerifyingPlatformAuthenticatorAvailable) return false;\n try {\n return await statics.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n}\n\n/**\n * Whether autofill-driven passkeys (`mediation: \"conditional\"`) are available.\n *\n * @returns `false` when the API is missing or throws.\n */\nexport async function isConditionalMediationAvailable(): Promise<boolean> {\n const statics = publicKeyCredentialStatics();\n if (!statics?.isConditionalMediationAvailable) return false;\n try {\n return await statics.isConditionalMediationAvailable();\n } catch {\n return false;\n }\n}\n\n/**\n * Map a thrown WebAuthn failure onto a {@link PasskeyError}.\n *\n * The secure-context check runs first for the same reason it does in the media\n * classifier: over plain HTTP the whole API is absent or refuses, and reporting\n * \"not supported\" sends a developer hunting for a polyfill for something an\n * `https://` URL fixes.\n *\n * @param error - Whatever `navigator.credentials` rejected with.\n * @param ceremony - Which ceremony was running, for the message.\n * @returns The classified error, ready to throw or to show.\n */\nexport function classifyPasskeyError(error: unknown, ceremony: PasskeyCeremony): PasskeyError {\n if (error instanceof PasskeyError) return error;\n\n if (typeof window !== \"undefined\" && !window.isSecureContext) {\n return new PasskeyError(\"insecure\", \"Passkeys require a secure (HTTPS) connection.\", error);\n }\n\n if (error instanceof DOMException) {\n switch (error.name) {\n case \"NotAllowedError\":\n return new PasskeyError(\n \"cancelled\",\n \"The passkey prompt was dismissed or timed out. The browser does not say which — it must not reveal whether a credential exists.\",\n error,\n );\n case \"InvalidStateError\":\n return new PasskeyError(\n \"already-registered\",\n \"This device already has a passkey for this account. Sign in with it instead of creating another.\",\n error,\n );\n case \"NotSupportedError\":\n return new PasskeyError(\n \"not-supported\",\n \"No authenticator here supports the requested algorithms. Check the server's pubKeyCredParams.\",\n error,\n );\n case \"SecurityError\":\n return new PasskeyError(\n \"rp-mismatch\",\n \"The relying-party id does not match this origin. rp.id must be the page's domain or a registrable parent of it.\",\n error,\n );\n case \"AbortError\":\n return new PasskeyError(\"aborted\", \"The passkey request was aborted.\", error);\n }\n }\n\n if (error instanceof TypeError) {\n return new PasskeyError(\n \"invalid-options\",\n `The ${ceremony} options the server sent are malformed. Check that challenge, user.id and credential ids are base64url.`,\n error,\n );\n }\n\n return new PasskeyError(\n \"unknown\",\n error instanceof Error\n ? error.message\n : `Unexpected error during the passkey ${ceremony} ceremony.`,\n error,\n );\n}\n\nfunction toDescriptors(\n list: { id: string; type: \"public-key\"; transports?: string[] }[] | undefined,\n): PublicKeyCredentialDescriptor[] | undefined {\n if (!list) return undefined;\n return list.map((item) => ({\n id: base64UrlToBytes(item.id) as unknown as BufferSource,\n type: item.type,\n transports: item.transports as AuthenticatorTransport[] | undefined,\n }));\n}\n\n/**\n * Build a WebAuthn client: the base64url ↔ `ArrayBuffer` plumbing, the two\n * ceremonies, and one classified error type.\n *\n * ## What your backend must do\n *\n * This is the **client half only**, and a WebAuthn client that documents only its\n * own half is unusable. Four routes are yours to implement:\n *\n * 1. `POST /webauthn/register/begin` → a {@link PasskeyCreationOptionsJSON}. Mint a\n * random `challenge` (≥16 bytes), store it against the session, and list the\n * user's existing credentials in `excludeCredentials`.\n * 2. `POST /webauthn/register/finish` ← a {@link PasskeyRegistrationJSON}. Verify\n * the challenge, `origin` and `type` inside `clientDataJSON`, parse the\n * attestation object, then store the credential id, public key and signature\n * counter.\n * 3. `POST /webauthn/signin/begin` → a {@link PasskeyRequestOptionsJSON}. New\n * challenge. Omit `allowCredentials` for a usernameless or autofill flow.\n * 4. `POST /webauthn/signin/finish` ← a {@link PasskeyAuthenticationJSON}. Look the\n * credential up by `id`, verify the signature over\n * `authenticatorData || sha256(clientDataJSON)`, and reject a signature counter\n * that did not grow (a clone). Only then issue your session token.\n *\n * @param options - Defaults applied when the server options omit them.\n * @returns A client usable from anywhere — React, a plain form, a worker.\n *\n * @example\n * const passkeys = createPasskeyClient({ rpId: \"acme.com\" });\n *\n * const options = await api.post(\"/webauthn/register/begin\");\n * const credential = await passkeys.register(options);\n * await api.post(\"/webauthn/register/finish\", { body: credential });\n */\nexport function createPasskeyClient(options: CreatePasskeyClientOptions = {}): PasskeyClient {\n const { rpId, timeoutMs = 60_000, credentials } = options;\n\n function container(): CredentialsContainerLike {\n if (credentials) return credentials;\n if (!isPasskeySupported()) {\n throw new PasskeyError(\n \"unsupported\",\n typeof window !== \"undefined\" && !window.isSecureContext\n ? \"Passkeys require a secure (HTTPS) connection.\"\n : \"This browser does not support passkeys (WebAuthn).\",\n );\n }\n return navigator.credentials as unknown as CredentialsContainerLike;\n }\n\n async function register(\n json: PasskeyCreationOptionsJSON,\n init: PasskeyRegisterInit = {},\n ): Promise<PasskeyRegistrationJSON> {\n const api = container();\n const publicKey: PublicKeyCredentialCreationOptions = {\n challenge: base64UrlToBytes(json.challenge) as unknown as BufferSource,\n rp: { name: json.rp.name, id: json.rp.id ?? rpId },\n user: {\n id: base64UrlToBytes(json.user.id) as unknown as BufferSource,\n name: json.user.name,\n displayName: json.user.displayName,\n },\n pubKeyCredParams: json.pubKeyCredParams ?? DEFAULT_PUB_KEY_CRED_PARAMS,\n timeout: json.timeout ?? timeoutMs,\n excludeCredentials: toDescriptors(json.excludeCredentials),\n authenticatorSelection: json.authenticatorSelection,\n attestation: json.attestation,\n extensions: json.extensions,\n };\n\n let credential: Credential | null;\n try {\n credential = await api.create({ publicKey, signal: init.signal });\n } catch (error) {\n throw classifyPasskeyError(error, \"register\");\n }\n if (!credential) {\n throw new PasskeyError(\"unknown\", \"The authenticator returned no credential.\");\n }\n\n const typed = credential as PublicKeyCredential;\n const response = typed.response as AuthenticatorAttestationResponse & AttestationExtras;\n const publicKeyBytes = response.getPublicKey?.();\n\n return {\n id: typed.id,\n rawId: bytesToBase64Url(typed.rawId),\n type: \"public-key\",\n authenticatorAttachment: typed.authenticatorAttachment ?? null,\n response: {\n clientDataJSON: bytesToBase64Url(response.clientDataJSON),\n attestationObject: bytesToBase64Url(response.attestationObject),\n transports: response.getTransports?.(),\n publicKeyAlgorithm: response.getPublicKeyAlgorithm?.(),\n publicKey: publicKeyBytes ? bytesToBase64Url(publicKeyBytes) : undefined,\n authenticatorData: response.getAuthenticatorData\n ? bytesToBase64Url(response.getAuthenticatorData())\n : undefined,\n },\n clientExtensionResults: typed.getClientExtensionResults(),\n };\n }\n\n async function authenticate(\n json: PasskeyRequestOptionsJSON,\n init: PasskeyAuthenticateInit = {},\n ): Promise<PasskeyAuthenticationJSON> {\n const api = container();\n const publicKey: PublicKeyCredentialRequestOptions = {\n challenge: base64UrlToBytes(json.challenge) as unknown as BufferSource,\n rpId: json.rpId ?? rpId,\n timeout: json.timeout ?? timeoutMs,\n allowCredentials: toDescriptors(json.allowCredentials),\n userVerification: json.userVerification,\n extensions: json.extensions,\n };\n\n let credential: Credential | null;\n try {\n credential = await api.get({\n publicKey,\n signal: init.signal,\n mediation: init.mediation,\n });\n } catch (error) {\n throw classifyPasskeyError(error, \"authenticate\");\n }\n if (!credential) {\n throw new PasskeyError(\"unknown\", \"The authenticator returned no credential.\");\n }\n\n const typed = credential as PublicKeyCredential;\n const response = typed.response as AuthenticatorAssertionResponse;\n\n return {\n id: typed.id,\n rawId: bytesToBase64Url(typed.rawId),\n type: \"public-key\",\n authenticatorAttachment: typed.authenticatorAttachment ?? null,\n response: {\n clientDataJSON: bytesToBase64Url(response.clientDataJSON),\n authenticatorData: bytesToBase64Url(response.authenticatorData),\n signature: bytesToBase64Url(response.signature),\n userHandle: response.userHandle ? bytesToBase64Url(response.userHandle) : null,\n },\n clientExtensionResults: typed.getClientExtensionResults(),\n };\n }\n\n return {\n register,\n authenticate,\n isSupported: () => credentials !== undefined || isPasskeySupported(),\n isPlatformAuthenticatorAvailable,\n isConditionalMediationAvailable,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"passkey.js","names":[],"sources":["../../src/auth/passkey.ts"],"sourcesContent":["/**\n * @tempest-limits file-lines, function-lines — the WebAuthn client half: the JSON\n * shapes both ceremonies exchange with a backend, base64url ↔ ArrayBuffer, the\n * capability probes and the error classifier. The two ceremonies are near-mirrors\n * that must not drift — register and authenticate encode the same credential fields\n * in the same order — and the file's docstring is also the specification of the four\n * backend routes it expects.\n */\n\nimport { base64ToBytes, bytesToBase64 } from \"@/utils/base64\";\n\n/**\n * Classified reason a passkey ceremony did not produce a credential.\n *\n * The kinds group the raw `DOMException.name` values the way a UI has to branch\n * on them, which is *not* how the spec groups them:\n *\n * - `\"cancelled\"` covers `NotAllowedError`, which the browser raises both when\n * the user dismissed the sheet and when the ceremony timed out. They are\n * indistinguishable **by design** — telling a site \"the user has no credential\n * for you\" would leak account existence — so a UI must treat them as one thing.\n * - `\"already-registered\"` (`InvalidStateError`) is not really a failure: this\n * device already holds a credential for this user. The correct reaction is\n * \"you are already set up on this device\", never a red error.\n * - `\"rp-mismatch\"` (`SecurityError`) is the single most common integration bug:\n * `rp.id` must equal the page's domain or a registrable parent of it.\n */\nexport type PasskeyErrorKind =\n | \"unsupported\"\n | \"insecure\"\n | \"cancelled\"\n | \"already-registered\"\n | \"not-supported\"\n | \"rp-mismatch\"\n | \"invalid-options\"\n | \"aborted\"\n | \"unknown\";\n\n/** Which ceremony was running, so the message can name it. */\nexport type PasskeyCeremony = \"register\" | \"authenticate\";\n\n/**\n * A passkey failure carrying a stable {@link PasskeyErrorKind} plus an English\n * message safe to show a user.\n *\n * A class rather than the plain `{ kind, message }` object the media classifier\n * returns, because these surface by rejecting a promise: an `Error` subclass keeps\n * stack traces, `instanceof` checks and logging intact, and `kind` is what code\n * branches on.\n */\nexport class PasskeyError extends Error {\n /** Stable, branchable classification. */\n readonly kind: PasskeyErrorKind;\n\n /**\n * Build a classified passkey error.\n *\n * @param kind - The classification a UI branches on.\n * @param message - English, user-safe explanation.\n * @param cause - The original thrown value, when there was one.\n */\n constructor(kind: PasskeyErrorKind, message: string, cause?: unknown) {\n super(message);\n this.name = \"PasskeyError\";\n this.kind = kind;\n this.cause = cause;\n }\n}\n\n/**\n * Minimal subset of `navigator.credentials` the passkey client touches.\n *\n * Declared here — the `<X>Like` pattern the SDK's adapters use — for two reasons:\n * jsdom has no `navigator.credentials` at all, so tests must inject a double; and\n * `mediation: \"conditional\"` is newer than some TypeScript DOM libs, which would\n * otherwise reject the call that makes autofill work.\n */\nexport interface CredentialsContainerLike {\n /** Runs the registration ceremony. */\n create(options: {\n publicKey: PublicKeyCredentialCreationOptions;\n signal?: AbortSignal;\n }): Promise<Credential | null>;\n /** Runs the authentication ceremony. */\n get(options: {\n publicKey: PublicKeyCredentialRequestOptions;\n signal?: AbortSignal;\n mediation?: string;\n }): Promise<Credential | null>;\n}\n\n/** How the browser should surface the authentication ceremony. */\nexport type PasskeyMediation = \"optional\" | \"conditional\" | \"required\" | \"silent\";\n\n/**\n * Server-issued registration options, in the base64url JSON shape every WebAuthn\n * backend speaks (`PublicKeyCredentialCreationOptionsJSON` in the spec).\n *\n * `challenge`, `user.id` and every `excludeCredentials[].id` are **base64url**\n * strings here and `ArrayBuffer`s in the DOM API. Converting them is the plumbing\n * this client owns.\n */\nexport interface PasskeyCreationOptionsJSON {\n /** Base64url server challenge. Single-use; the server must remember it. */\n challenge: string;\n /** Relying party. `id` defaults to the client's `rpId`, then to the origin. */\n rp: { name: string; id?: string };\n /** The account. `id` is base64url of an opaque, stable user handle. */\n user: { id: string; name: string; displayName: string };\n /** Allowed COSE algorithms. Defaults to {@link DEFAULT_PUB_KEY_CRED_PARAMS}. */\n pubKeyCredParams?: { type: \"public-key\"; alg: number }[];\n /** Ceremony timeout in ms. Defaults to the client's `timeoutMs`. */\n timeout?: number;\n /** Credentials this user already has, so the authenticator refuses a duplicate. */\n excludeCredentials?: { id: string; type: \"public-key\"; transports?: string[] }[];\n /** Resident-key / user-verification / attachment requirements. */\n authenticatorSelection?: AuthenticatorSelectionCriteria;\n /** Attestation conveyance. Leave unset (`\"none\"`) unless you verify it. */\n attestation?: AttestationConveyancePreference;\n /** Client extension inputs (`credProps`, `largeBlob`, …). */\n extensions?: AuthenticationExtensionsClientInputs;\n}\n\n/** Server-issued authentication options, base64url JSON. */\nexport interface PasskeyRequestOptionsJSON {\n /** Base64url server challenge. */\n challenge: string;\n /** Relying party id. Defaults to the client's `rpId`, then to the origin. */\n rpId?: string;\n /** Ceremony timeout in ms. Defaults to the client's `timeoutMs`. */\n timeout?: number;\n /** Restrict to these credentials. **Omit it** for usernameless / autofill flows. */\n allowCredentials?: { id: string; type: \"public-key\"; transports?: string[] }[];\n /** Whether the authenticator must verify the user (biometric / PIN). */\n userVerification?: UserVerificationRequirement;\n /** Client extension inputs. */\n extensions?: AuthenticationExtensionsClientInputs;\n}\n\n/** What the client sends to the backend to finish registration. */\nexport interface PasskeyRegistrationJSON {\n /** Base64url credential id. */\n id: string;\n /** Same bytes as `id`; both are sent because servers differ on which they read. */\n rawId: string;\n type: \"public-key\";\n /** `\"platform\"` (this device) or `\"cross-platform\"` (a phone or key). */\n authenticatorAttachment: string | null;\n response: {\n /** Base64url client data — the server re-checks challenge, origin and type. */\n clientDataJSON: string;\n /** Base64url attestation object, holding the new public key. */\n attestationObject: string;\n /** Transports the authenticator advertises, when the browser exposes them. */\n transports?: string[];\n /** COSE algorithm of the new key, when the browser exposes it. */\n publicKeyAlgorithm?: number;\n /** Base64url SPKI public key, when the browser exposes it. */\n publicKey?: string;\n /** Base64url authenticator data, when the browser exposes it. */\n authenticatorData?: string;\n };\n /** Extension outputs — `credProps.rk` tells you whether it is discoverable. */\n clientExtensionResults: AuthenticationExtensionsClientOutputs;\n}\n\n/** What the client sends to the backend to finish authentication. */\nexport interface PasskeyAuthenticationJSON {\n /** Base64url credential id — the server looks up the stored public key by it. */\n id: string;\n /** Same bytes as `id`. */\n rawId: string;\n type: \"public-key\";\n /** `\"platform\"` or `\"cross-platform\"`. */\n authenticatorAttachment: string | null;\n response: {\n /** Base64url client data. */\n clientDataJSON: string;\n /** Base64url authenticator data, carrying the signature counter. */\n authenticatorData: string;\n /** Base64url signature over `authenticatorData || sha256(clientDataJSON)`. */\n signature: string;\n /** Base64url user handle — present on discoverable credentials, else null. */\n userHandle: string | null;\n };\n /** Extension outputs. */\n clientExtensionResults: AuthenticationExtensionsClientOutputs;\n}\n\n/** Per-call knobs for {@link PasskeyClient.register}. */\nexport interface PasskeyRegisterInit {\n /** Cancel the ceremony (closes the browser sheet). */\n signal?: AbortSignal;\n}\n\n/** Per-call knobs for {@link PasskeyClient.authenticate}. */\nexport interface PasskeyAuthenticateInit extends PasskeyRegisterInit {\n /**\n * `\"conditional\"` is the autofill flow: no modal, the browser offers passkeys\n * inside a field marked `autocomplete=\"webauthn\"`. Requires a `signal`, and\n * only one conditional request may be live per page.\n */\n mediation?: PasskeyMediation;\n}\n\n/** Framework-free WebAuthn client. Build one with {@link createPasskeyClient}. */\nexport interface PasskeyClient {\n /** Run the registration ceremony and return the JSON your backend verifies. */\n register(\n options: PasskeyCreationOptionsJSON,\n init?: PasskeyRegisterInit,\n ): Promise<PasskeyRegistrationJSON>;\n /** Run the authentication ceremony and return the JSON your backend verifies. */\n authenticate(\n options: PasskeyRequestOptionsJSON,\n init?: PasskeyAuthenticateInit,\n ): Promise<PasskeyAuthenticationJSON>;\n /**\n * Whether this client can run a ceremony at all — the WebAuthn API exists, or a\n * `credentials` container was injected.\n */\n isSupported(): boolean;\n /** Whether this device has a built-in authenticator (Face ID, Hello, …). */\n isPlatformAuthenticatorAvailable(): Promise<boolean>;\n /** Whether autofill-driven (`\"conditional\"`) requests are available. */\n isConditionalMediationAvailable(): Promise<boolean>;\n}\n\n/** Options for {@link createPasskeyClient}. */\nexport interface CreatePasskeyClientOptions {\n /**\n * Default relying-party id, applied when the server options omit one. Must be\n * the page's domain or a registrable parent of it (`app.acme.com` may use\n * `acme.com`, never the other way round).\n */\n rpId?: string;\n /** Default ceremony timeout in ms. Default `60_000`. */\n timeoutMs?: number;\n /** `navigator.credentials` replacement, for tests. */\n credentials?: CredentialsContainerLike;\n}\n\n/**\n * COSE algorithms offered when the server sends no `pubKeyCredParams`, in\n * preference order.\n *\n * `-8` is Ed25519, which modern authenticators prefer and which produces the\n * smallest signatures. `-7` is ES256, the one algorithm every WebAuthn\n * authenticator supports. `-257` is RS256, needed for TPM-backed Windows Hello.\n * Offering all three is what avoids a `NotSupportedError` on some device you do\n * not own; a server that cannot verify one of them should send its own list.\n */\nexport const DEFAULT_PUB_KEY_CRED_PARAMS: { type: \"public-key\"; alg: number }[] = [\n { type: \"public-key\", alg: -8 },\n { type: \"public-key\", alg: -7 },\n { type: \"public-key\", alg: -257 },\n];\n\n/** Static members of `PublicKeyCredential` that are not in every DOM lib yet. */\ninterface PublicKeyCredentialStatics {\n isUserVerifyingPlatformAuthenticatorAvailable?: () => Promise<boolean>;\n isConditionalMediationAvailable?: () => Promise<boolean>;\n}\n\n/** The browser-supplied extras on an attestation response, all optional. */\ninterface AttestationExtras {\n getTransports?: () => string[];\n getPublicKey?: () => ArrayBuffer | null;\n getPublicKeyAlgorithm?: () => number;\n getAuthenticatorData?: () => ArrayBuffer;\n}\n\nfunction publicKeyCredentialStatics(): PublicKeyCredentialStatics | undefined {\n return (globalThis as { PublicKeyCredential?: PublicKeyCredentialStatics }).PublicKeyCredential;\n}\n\n/**\n * Decode a base64url string into bytes.\n *\n * WebAuthn transports every binary field as base64url (`-`/`_`, no padding)\n * because that is what survives JSON, while the DOM API insists on\n * `ArrayBuffer`. Getting this pair wrong — usually by feeding plain base64 to\n * `atob` and losing the last byte — is the classic broken-WebAuthn bug, which is\n * why the SDK owns it instead of leaving it to each app.\n *\n * This is the WebAuthn-facing name for {@link base64ToBytes}; the codec itself is\n * shared, so the padding rule has one implementation rather than three.\n *\n * @param value - Base64url text, with or without `=` padding.\n * @returns The decoded bytes.\n */\nexport function base64UrlToBytes(value: string): Uint8Array<ArrayBuffer> {\n return base64ToBytes(value);\n}\n\n/**\n * Encode bytes as an unpadded base64url string.\n *\n * Normalises `ArrayBuffer` to a view — which is what the WebAuthn response\n * fields hand over — and delegates the encoding to {@link bytesToBase64}.\n *\n * @param value - Bytes to encode, as a view or a raw buffer.\n * @returns Base64url text, safe to put in JSON and in a URL.\n */\nexport function bytesToBase64Url(value: ArrayBuffer | Uint8Array): string {\n const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);\n return bytesToBase64(bytes, { urlSafe: true });\n}\n\n/**\n * Whether this browser exposes WebAuthn at all.\n *\n * Note that \"supported\" is not \"usable\": WebAuthn also requires a secure context,\n * and a device may have no authenticator. Use\n * {@link isPlatformAuthenticatorAvailable} before offering a passkey button.\n */\nexport function isPasskeySupported(): boolean {\n return (\n typeof window !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n navigator.credentials !== undefined &&\n typeof navigator.credentials.create === \"function\" &&\n publicKeyCredentialStatics() !== undefined\n );\n}\n\n/**\n * Whether the device has a **built-in** authenticator — Face ID, Touch ID,\n * Windows Hello, an Android screen lock.\n *\n * This is the check that decides whether \"Entrar com passkey\" may be shown at\n * all. `isPasskeySupported()` is true on a desktop with no biometrics and no\n * security key, and offering a passkey there sends the user into a sheet that can\n * only be cancelled. A `false` here does not forbid passkeys — a phone can still\n * be used over hybrid/QR — it means the flow needs a second step, so present it\n * as \"usar meu celular\", not as one tap.\n *\n * @returns `false` when the API is missing, so a caller never has to null-check.\n */\nexport async function isPlatformAuthenticatorAvailable(): Promise<boolean> {\n const statics = publicKeyCredentialStatics();\n if (!statics?.isUserVerifyingPlatformAuthenticatorAvailable) return false;\n try {\n return await statics.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n}\n\n/**\n * Whether autofill-driven passkeys (`mediation: \"conditional\"`) are available.\n *\n * @returns `false` when the API is missing or throws.\n */\nexport async function isConditionalMediationAvailable(): Promise<boolean> {\n const statics = publicKeyCredentialStatics();\n if (!statics?.isConditionalMediationAvailable) return false;\n try {\n return await statics.isConditionalMediationAvailable();\n } catch {\n return false;\n }\n}\n\n/**\n * Map a thrown WebAuthn failure onto a {@link PasskeyError}.\n *\n * The secure-context check runs first for the same reason it does in the media\n * classifier: over plain HTTP the whole API is absent or refuses, and reporting\n * \"not supported\" sends a developer hunting for a polyfill for something an\n * `https://` URL fixes.\n *\n * @param error - Whatever `navigator.credentials` rejected with.\n * @param ceremony - Which ceremony was running, for the message.\n * @returns The classified error, ready to throw or to show.\n */\nexport function classifyPasskeyError(error: unknown, ceremony: PasskeyCeremony): PasskeyError {\n if (error instanceof PasskeyError) return error;\n\n if (typeof window !== \"undefined\" && !window.isSecureContext) {\n return new PasskeyError(\"insecure\", \"Passkeys require a secure (HTTPS) connection.\", error);\n }\n\n if (error instanceof DOMException) {\n switch (error.name) {\n case \"NotAllowedError\":\n return new PasskeyError(\n \"cancelled\",\n \"The passkey prompt was dismissed or timed out. The browser does not say which — it must not reveal whether a credential exists.\",\n error,\n );\n case \"InvalidStateError\":\n return new PasskeyError(\n \"already-registered\",\n \"This device already has a passkey for this account. Sign in with it instead of creating another.\",\n error,\n );\n case \"NotSupportedError\":\n return new PasskeyError(\n \"not-supported\",\n \"No authenticator here supports the requested algorithms. Check the server's pubKeyCredParams.\",\n error,\n );\n case \"SecurityError\":\n return new PasskeyError(\n \"rp-mismatch\",\n \"The relying-party id does not match this origin. rp.id must be the page's domain or a registrable parent of it.\",\n error,\n );\n case \"AbortError\":\n return new PasskeyError(\"aborted\", \"The passkey request was aborted.\", error);\n }\n }\n\n if (error instanceof TypeError) {\n return new PasskeyError(\n \"invalid-options\",\n `The ${ceremony} options the server sent are malformed. Check that challenge, user.id and credential ids are base64url.`,\n error,\n );\n }\n\n return new PasskeyError(\n \"unknown\",\n error instanceof Error\n ? error.message\n : `Unexpected error during the passkey ${ceremony} ceremony.`,\n error,\n );\n}\n\nfunction toDescriptors(\n list: { id: string; type: \"public-key\"; transports?: string[] }[] | undefined,\n): PublicKeyCredentialDescriptor[] | undefined {\n if (!list) return undefined;\n return list.map((item) => ({\n id: base64UrlToBytes(item.id) as unknown as BufferSource,\n type: item.type,\n transports: item.transports as AuthenticatorTransport[] | undefined,\n }));\n}\n\n/**\n * Build a WebAuthn client: the base64url ↔ `ArrayBuffer` plumbing, the two\n * ceremonies, and one classified error type.\n *\n * ## What your backend must do\n *\n * This is the **client half only**, and a WebAuthn client that documents only its\n * own half is unusable. Four routes are yours to implement:\n *\n * 1. `POST /webauthn/register/begin` → a {@link PasskeyCreationOptionsJSON}. Mint a\n * random `challenge` (≥16 bytes), store it against the session, and list the\n * user's existing credentials in `excludeCredentials`.\n * 2. `POST /webauthn/register/finish` ← a {@link PasskeyRegistrationJSON}. Verify\n * the challenge, `origin` and `type` inside `clientDataJSON`, parse the\n * attestation object, then store the credential id, public key and signature\n * counter.\n * 3. `POST /webauthn/signin/begin` → a {@link PasskeyRequestOptionsJSON}. New\n * challenge. Omit `allowCredentials` for a usernameless or autofill flow.\n * 4. `POST /webauthn/signin/finish` ← a {@link PasskeyAuthenticationJSON}. Look the\n * credential up by `id`, verify the signature over\n * `authenticatorData || sha256(clientDataJSON)`, and reject a signature counter\n * that did not grow (a clone). Only then issue your session token.\n *\n * @param options - Defaults applied when the server options omit them.\n * @returns A client usable from anywhere — React, a plain form, a worker.\n *\n * @example\n * const passkeys = createPasskeyClient({ rpId: \"acme.com\" });\n *\n * const options = await api.post(\"/webauthn/register/begin\");\n * const credential = await passkeys.register(options);\n * await api.post(\"/webauthn/register/finish\", { body: credential });\n */\nexport function createPasskeyClient(options: CreatePasskeyClientOptions = {}): PasskeyClient {\n const { rpId, timeoutMs = 60_000, credentials } = options;\n\n function container(): CredentialsContainerLike {\n if (credentials) return credentials;\n if (!isPasskeySupported()) {\n throw new PasskeyError(\n \"unsupported\",\n typeof window !== \"undefined\" && !window.isSecureContext\n ? \"Passkeys require a secure (HTTPS) connection.\"\n : \"This browser does not support passkeys (WebAuthn).\",\n );\n }\n return navigator.credentials as unknown as CredentialsContainerLike;\n }\n\n async function register(\n json: PasskeyCreationOptionsJSON,\n init: PasskeyRegisterInit = {},\n ): Promise<PasskeyRegistrationJSON> {\n const api = container();\n const publicKey: PublicKeyCredentialCreationOptions = {\n challenge: base64UrlToBytes(json.challenge) as unknown as BufferSource,\n rp: { name: json.rp.name, id: json.rp.id ?? rpId },\n user: {\n id: base64UrlToBytes(json.user.id) as unknown as BufferSource,\n name: json.user.name,\n displayName: json.user.displayName,\n },\n pubKeyCredParams: json.pubKeyCredParams ?? DEFAULT_PUB_KEY_CRED_PARAMS,\n timeout: json.timeout ?? timeoutMs,\n excludeCredentials: toDescriptors(json.excludeCredentials),\n authenticatorSelection: json.authenticatorSelection,\n attestation: json.attestation,\n extensions: json.extensions,\n };\n\n let credential: Credential | null;\n try {\n credential = await api.create({ publicKey, signal: init.signal });\n } catch (error) {\n throw classifyPasskeyError(error, \"register\");\n }\n if (!credential) {\n throw new PasskeyError(\"unknown\", \"The authenticator returned no credential.\");\n }\n\n const typed = credential as PublicKeyCredential;\n const response = typed.response as AuthenticatorAttestationResponse & AttestationExtras;\n const publicKeyBytes = response.getPublicKey?.();\n\n return {\n id: typed.id,\n rawId: bytesToBase64Url(typed.rawId),\n type: \"public-key\",\n authenticatorAttachment: typed.authenticatorAttachment ?? null,\n response: {\n clientDataJSON: bytesToBase64Url(response.clientDataJSON),\n attestationObject: bytesToBase64Url(response.attestationObject),\n transports: response.getTransports?.(),\n publicKeyAlgorithm: response.getPublicKeyAlgorithm?.(),\n publicKey: publicKeyBytes ? bytesToBase64Url(publicKeyBytes) : undefined,\n authenticatorData: response.getAuthenticatorData\n ? bytesToBase64Url(response.getAuthenticatorData())\n : undefined,\n },\n clientExtensionResults: typed.getClientExtensionResults(),\n };\n }\n\n async function authenticate(\n json: PasskeyRequestOptionsJSON,\n init: PasskeyAuthenticateInit = {},\n ): Promise<PasskeyAuthenticationJSON> {\n const api = container();\n const publicKey: PublicKeyCredentialRequestOptions = {\n challenge: base64UrlToBytes(json.challenge) as unknown as BufferSource,\n rpId: json.rpId ?? rpId,\n timeout: json.timeout ?? timeoutMs,\n allowCredentials: toDescriptors(json.allowCredentials),\n userVerification: json.userVerification,\n extensions: json.extensions,\n };\n\n let credential: Credential | null;\n try {\n credential = await api.get({\n publicKey,\n signal: init.signal,\n mediation: init.mediation,\n });\n } catch (error) {\n throw classifyPasskeyError(error, \"authenticate\");\n }\n if (!credential) {\n throw new PasskeyError(\"unknown\", \"The authenticator returned no credential.\");\n }\n\n const typed = credential as PublicKeyCredential;\n const response = typed.response as AuthenticatorAssertionResponse;\n\n return {\n id: typed.id,\n rawId: bytesToBase64Url(typed.rawId),\n type: \"public-key\",\n authenticatorAttachment: typed.authenticatorAttachment ?? null,\n response: {\n clientDataJSON: bytesToBase64Url(response.clientDataJSON),\n authenticatorData: bytesToBase64Url(response.authenticatorData),\n signature: bytesToBase64Url(response.signature),\n userHandle: response.userHandle ? bytesToBase64Url(response.userHandle) : null,\n },\n clientExtensionResults: typed.getClientExtensionResults(),\n };\n }\n\n return {\n register,\n authenticate,\n isSupported: () => credentials !== undefined || isPasskeySupported(),\n isPlatformAuthenticatorAvailable,\n isConditionalMediationAvailable,\n };\n}\n"],"mappings":"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"}
package/dist/charts.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./charts/scales.cjs"),t=require("./charts/palette.cjs"),n=require("./charts/use-chart-colors.cjs"),r=require("./charts/AreaChart.cjs"),i=require("./charts/BarChart.cjs"),a=require("./charts/LineChart.cjs"),o=require("./charts/PieChart.cjs"),s=require("./charts/RadarChart.cjs");exports.AreaChart=r.AreaChart,exports.BarChart=i.BarChart,exports.DEFAULT_CHART_COLORS=t.DEFAULT_CHART_COLORS,exports.DIVERGING_STEP_COUNT=e.DIVERGING_STEP_COUNT,exports.LineChart=a.LineChart,exports.ORDINAL_START_STEP=e.ORDINAL_START_STEP,exports.PieChart=o.PieChart,exports.RadarChart=s.RadarChart,exports.SEQUENTIAL_STEP_COUNT=e.SEQUENTIAL_STEP_COUNT,exports.divergingScale=e.divergingScale,exports.resolveChartChrome=t.resolveChartChrome,exports.resolveChartColors=t.resolveChartColors,exports.scaleSteps=e.scaleSteps,exports.sequentialScale=e.sequentialScale,exports.useChartColors=n.useChartColors;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./charts/palette.cjs"),t=require("./charts/use-chart-colors.cjs"),n=require("./charts/scales.cjs"),r=require("./charts/AreaChart.cjs"),i=require("./charts/BarChart.cjs"),a=require("./charts/LineChart.cjs"),o=require("./charts/PieChart.cjs"),s=require("./charts/RadarChart.cjs");exports.AreaChart=r.AreaChart,exports.BarChart=i.BarChart,exports.DEFAULT_CHART_COLORS=e.DEFAULT_CHART_COLORS,exports.DIVERGING_STEP_COUNT=n.DIVERGING_STEP_COUNT,exports.LineChart=a.LineChart,exports.ORDINAL_START_STEP=n.ORDINAL_START_STEP,exports.PieChart=o.PieChart,exports.RadarChart=s.RadarChart,exports.SEQUENTIAL_STEP_COUNT=n.SEQUENTIAL_STEP_COUNT,exports.divergingScale=n.divergingScale,exports.resolveChartChrome=e.resolveChartChrome,exports.resolveChartColors=e.resolveChartColors,exports.scaleSteps=n.scaleSteps,exports.sequentialScale=n.sequentialScale,exports.useChartColors=t.useChartColors;
package/dist/charts.js CHANGED
@@ -1,9 +1,9 @@
1
- import { DIVERGING_STEP_COUNT as e, ORDINAL_START_STEP as t, SEQUENTIAL_STEP_COUNT as n, divergingScale as r, scaleSteps as i, sequentialScale as a } from "./charts/scales.js";
2
- import { DEFAULT_CHART_COLORS as o, resolveChartChrome as s, resolveChartColors as c } from "./charts/palette.js";
3
- import { useChartColors as l } from "./charts/use-chart-colors.js";
1
+ import { DEFAULT_CHART_COLORS as e, resolveChartChrome as t, resolveChartColors as n } from "./charts/palette.js";
2
+ import { useChartColors as r } from "./charts/use-chart-colors.js";
3
+ import { DIVERGING_STEP_COUNT as i, ORDINAL_START_STEP as a, SEQUENTIAL_STEP_COUNT as o, divergingScale as s, scaleSteps as c, sequentialScale as l } from "./charts/scales.js";
4
4
  import { AreaChart as u } from "./charts/AreaChart.js";
5
5
  import { BarChart as d } from "./charts/BarChart.js";
6
6
  import { LineChart as f } from "./charts/LineChart.js";
7
7
  import { PieChart as p } from "./charts/PieChart.js";
8
8
  import { RadarChart as m } from "./charts/RadarChart.js";
9
- export { u as AreaChart, d as BarChart, o as DEFAULT_CHART_COLORS, e as DIVERGING_STEP_COUNT, f as LineChart, t as ORDINAL_START_STEP, p as PieChart, m as RadarChart, n as SEQUENTIAL_STEP_COUNT, r as divergingScale, s as resolveChartChrome, c as resolveChartColors, i as scaleSteps, a as sequentialScale, l as useChartColors };
9
+ export { u as AreaChart, d as BarChart, e as DEFAULT_CHART_COLORS, i as DIVERGING_STEP_COUNT, f as LineChart, a as ORDINAL_START_STEP, p as PieChart, m as RadarChart, o as SEQUENTIAL_STEP_COUNT, s as divergingScale, t as resolveChartChrome, n as resolveChartColors, c as scaleSteps, l as sequentialScale, r as useChartColors };
@@ -1,3 +1,3 @@
1
- const e=require("../../utils/cn.cjs"),t=require("../../utils/numbers.cjs"),n=require("../VisuallyHidden/VisuallyHidden.cjs"),r=require("../CopyButton/CopyButton.cjs"),i=require("../Collapsible/Collapsible.cjs"),a=require("./ai-chat-turns.cjs"),o=require("./AIChat.module.cjs"),s=require("../Markdown/Markdown.cjs");let c=require("react"),l=require("react/jsx-runtime"),u=require("lucide-react");function d({message:d,locale:f=`pt-BR`,canRegenerate:p=!1,onRegenerate:m,onFeedback:h,onEditSubmit:g,onEditError:_,onRetry:v,renderAvatar:y,renderContent:b,vote:x,defaultReasoningOpen:S=!1,showLineNumbers:C=!1}){let w=a.aiChatStrings(f),{role:T,content:E,reasoning:D,streaming:O,error:k,model:A,createdAt:j,attachments:M}=d,[N,P]=(0,c.useState)(null),[F,I]=(0,c.useState)(!1),[L,R]=(0,c.useState)(E),[z,B]=(0,c.useState)(!1),V=x??N,H=T===`user`,U=(0,c.useMemo)(()=>(0,l.jsx)(s.Markdown,{source:E,showLineNumbers:C,className:o.default.markdownRoot}),[E,C]),W=b?b(d):H?(0,l.jsx)(`div`,{className:o.default.plain,children:E}):E===``?null:U,G=async()=>{let e=L.trim();if(!(!e||z||!g)){B(!0);try{await g(d,e),I(!1)}catch(e){_?.(e)}finally{B(!1)}}},K=e=>{V!==e&&(P(e),h?.(d,e))},q=!O&&!F,J=h!==void 0||p&&m!==void 0;return(0,l.jsxs)(`article`,{className:e.cn(o.default.turn,H&&o.default.userTurn,T===`system`&&o.default.systemTurn,O&&o.default.streamingTurn),"aria-busy":O||void 0,"data-role":T,children:[(0,l.jsxs)(`header`,{className:o.default.turnHeader,children:[y&&(0,l.jsx)(`span`,{className:o.default.avatar,"aria-hidden":`true`,children:y(d)}),(0,l.jsx)(`span`,{className:e.cn(o.default.role,H&&o.default.visuallyHiddenRole),children:a.roleLabel(T,w)}),A&&!H&&(0,l.jsx)(`span`,{className:o.default.model,children:A}),j!==void 0&&(0,l.jsx)(`time`,{className:o.default.time,dateTime:new Date(j).toISOString(),children:a.turnTime(j,f)})]}),M&&M.length>0&&(0,l.jsx)(`ul`,{className:o.default.attachments,children:M.map(e=>(0,l.jsx)(`li`,{className:o.default.attachment,children:e.url?(0,l.jsx)(`img`,{className:o.default.thumb,src:e.url,alt:e.name}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`span`,{className:o.default.attachmentName,children:e.name}),(0,l.jsx)(`span`,{className:o.default.attachmentMeta,children:e.size===void 0?e.mimeType:t.formatBytes(e.size)})]})},e.id))}),D&&(0,l.jsx)(i.Collapsible,{className:o.default.reasoning,defaultOpen:S||O===!0&&E===``,trigger:(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(u.ChevronRight,{className:o.default.reasoningChevron,size:14,"aria-hidden":!0}),w.reasoning]}),children:(0,l.jsx)(`div`,{className:o.default.reasoningBody,children:D})}),F?(0,l.jsxs)(`div`,{className:o.default.editor,children:[(0,l.jsx)(n.VisuallyHidden,{children:(0,l.jsx)(`label`,{htmlFor:`${d.id}-edit`,children:w.editing})}),(0,l.jsx)(`textarea`,{id:`${d.id}-edit`,className:o.default.editField,value:L,rows:Math.min(L.split(`
1
+ const e=require("../../utils/cn.cjs"),t=require("../VisuallyHidden/VisuallyHidden.cjs"),n=require("../../utils/numbers.cjs"),r=require("../CopyButton/CopyButton.cjs"),i=require("../Collapsible/Collapsible.cjs"),a=require("./ai-chat-turns.cjs"),o=require("./AIChat.module.cjs"),s=require("../Markdown/Markdown.cjs");let c=require("react"),l=require("react/jsx-runtime"),u=require("lucide-react");function d({message:d,locale:f=`pt-BR`,canRegenerate:p=!1,onRegenerate:m,onFeedback:h,onEditSubmit:g,onEditError:_,onRetry:v,renderAvatar:y,renderContent:b,vote:x,defaultReasoningOpen:S=!1,showLineNumbers:C=!1}){let w=a.aiChatStrings(f),{role:T,content:E,reasoning:D,streaming:O,error:k,model:A,createdAt:j,attachments:M}=d,[N,P]=(0,c.useState)(null),[F,I]=(0,c.useState)(!1),[L,R]=(0,c.useState)(E),[z,B]=(0,c.useState)(!1),V=x??N,H=T===`user`,U=(0,c.useMemo)(()=>(0,l.jsx)(s.Markdown,{source:E,showLineNumbers:C,className:o.default.markdownRoot}),[E,C]),W=b?b(d):H?(0,l.jsx)(`div`,{className:o.default.plain,children:E}):E===``?null:U,G=async()=>{let e=L.trim();if(!(!e||z||!g)){B(!0);try{await g(d,e),I(!1)}catch(e){_?.(e)}finally{B(!1)}}},K=e=>{V!==e&&(P(e),h?.(d,e))},q=!O&&!F,J=h!==void 0||p&&m!==void 0;return(0,l.jsxs)(`article`,{className:e.cn(o.default.turn,H&&o.default.userTurn,T===`system`&&o.default.systemTurn,O&&o.default.streamingTurn),"aria-busy":O||void 0,"data-role":T,children:[(0,l.jsxs)(`header`,{className:o.default.turnHeader,children:[y&&(0,l.jsx)(`span`,{className:o.default.avatar,"aria-hidden":`true`,children:y(d)}),(0,l.jsx)(`span`,{className:e.cn(o.default.role,H&&o.default.visuallyHiddenRole),children:a.roleLabel(T,w)}),A&&!H&&(0,l.jsx)(`span`,{className:o.default.model,children:A}),j!==void 0&&(0,l.jsx)(`time`,{className:o.default.time,dateTime:new Date(j).toISOString(),children:a.turnTime(j,f)})]}),M&&M.length>0&&(0,l.jsx)(`ul`,{className:o.default.attachments,children:M.map(e=>(0,l.jsx)(`li`,{className:o.default.attachment,children:e.url?(0,l.jsx)(`img`,{className:o.default.thumb,src:e.url,alt:e.name}):(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`span`,{className:o.default.attachmentName,children:e.name}),(0,l.jsx)(`span`,{className:o.default.attachmentMeta,children:e.size===void 0?e.mimeType:n.formatBytes(e.size)})]})},e.id))}),D&&(0,l.jsx)(i.Collapsible,{className:o.default.reasoning,defaultOpen:S||O===!0&&E===``,trigger:(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(u.ChevronRight,{className:o.default.reasoningChevron,size:14,"aria-hidden":!0}),w.reasoning]}),children:(0,l.jsx)(`div`,{className:o.default.reasoningBody,children:D})}),F?(0,l.jsxs)(`div`,{className:o.default.editor,children:[(0,l.jsx)(t.VisuallyHidden,{children:(0,l.jsx)(`label`,{htmlFor:`${d.id}-edit`,children:w.editing})}),(0,l.jsx)(`textarea`,{id:`${d.id}-edit`,className:o.default.editField,value:L,rows:Math.min(L.split(`
2
2
  `).length+1,10),onChange:e=>R(e.target.value)}),(0,l.jsxs)(`div`,{className:o.default.editActions,children:[(0,l.jsx)(`button`,{type:`button`,className:o.default.ghost,onClick:()=>{R(E),I(!1)},children:w.cancel}),(0,l.jsx)(`button`,{type:`button`,className:o.default.primary,disabled:z||L.trim()===``,onClick:()=>void G(),children:w.save})]})]}):(0,l.jsxs)(`div`,{className:e.cn(o.default.body,O&&o.default.streamingBody),children:[W,O===!0&&E===``&&(0,l.jsxs)(`span`,{className:o.default.dots,"aria-hidden":`true`,children:[(0,l.jsx)(`span`,{}),(0,l.jsx)(`span`,{}),(0,l.jsx)(`span`,{})]})]}),k&&(0,l.jsxs)(`p`,{className:o.default.error,role:`alert`,children:[(0,l.jsx)(`span`,{children:k}),v&&(0,l.jsx)(`button`,{type:`button`,className:o.default.retry,onClick:()=>v(d),children:w.retry})]}),q&&(0,l.jsxs)(`div`,{className:o.default.actions,"aria-label":w.turnActions,role:`group`,children:[(0,l.jsx)(r.CopyButton,{className:o.default.action,value:E,"aria-label":w.copy,title:w.copy,children:(0,l.jsx)(u.Copy,{size:14,"aria-hidden":!0})}),H&&g&&(0,l.jsx)(`button`,{type:`button`,className:o.default.action,"aria-label":w.edit,title:w.edit,onClick:()=>{R(E),I(!0)},children:(0,l.jsx)(u.Pencil,{size:14,"aria-hidden":!0})}),!H&&J&&(0,l.jsxs)(l.Fragment,{children:[p&&m&&(0,l.jsx)(`button`,{type:`button`,className:o.default.action,"aria-label":w.regenerate,title:w.regenerate,onClick:()=>m(d),children:(0,l.jsx)(u.RefreshCw,{size:14,"aria-hidden":!0})}),h&&(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(`button`,{type:`button`,className:e.cn(o.default.action,V===`up`&&o.default.actionActive),"aria-label":w.good,title:w.good,"aria-pressed":V===`up`,onClick:()=>K(`up`),children:(0,l.jsx)(u.ThumbsUp,{size:14,"aria-hidden":!0})}),(0,l.jsx)(`button`,{type:`button`,className:e.cn(o.default.action,V===`down`&&o.default.actionActive),"aria-label":w.bad,title:w.bad,"aria-pressed":V===`down`,onClick:()=>K(`down`),children:(0,l.jsx)(u.ThumbsDown,{size:14,"aria-hidden":!0})})]})]})]})]})}exports.AIChatTurn=d;
3
3
  //# sourceMappingURL=AIChatTurn.cjs.map
@@ -1,6 +1,6 @@
1
1
  import { cn as e } from "../../utils/cn.js";
2
- import { formatBytes as t } from "../../utils/numbers.js";
3
- import { VisuallyHidden as n } from "../VisuallyHidden/VisuallyHidden.js";
2
+ import { VisuallyHidden as t } from "../VisuallyHidden/VisuallyHidden.js";
3
+ import { formatBytes as n } from "../../utils/numbers.js";
4
4
  import { CopyButton as ee } from "../CopyButton/CopyButton.js";
5
5
  import { Collapsible as r } from "../Collapsible/Collapsible.js";
6
6
  import { aiChatStrings as i, roleLabel as a, turnTime as o } from "./ai-chat-turns.js";
@@ -74,7 +74,7 @@ function b({ message: b, locale: x = "pt-BR", canRegenerate: S = !1, onRegenerat
74
74
  children: e.name
75
75
  }), /* @__PURE__ */ f("span", {
76
76
  className: s.attachmentMeta,
77
- children: e.size === void 0 ? e.mimeType : t(e.size)
77
+ children: e.size === void 0 ? e.mimeType : n(e.size)
78
78
  })] })
79
79
  }, e.id))
80
80
  }),
@@ -94,7 +94,7 @@ function b({ message: b, locale: x = "pt-BR", canRegenerate: S = !1, onRegenerat
94
94
  W ? /* @__PURE__ */ p("div", {
95
95
  className: s.editor,
96
96
  children: [
97
- /* @__PURE__ */ f(n, { children: /* @__PURE__ */ f("label", {
97
+ /* @__PURE__ */ f(t, { children: /* @__PURE__ */ f("label", {
98
98
  htmlFor: `${b.id}-edit`,
99
99
  children: N.editing
100
100
  }) }),
@@ -1 +1 @@
1
- {"version":3,"file":"use-sticky-body-warning.cjs","names":[],"sources":["../../../src/components/AppBar/use-sticky-body-warning.ts"],"sourcesContent":["import { useEffect } from \"react\";\n\nimport { isDevBuild } from \"../../utils\";\n\n/**\n * The one line of the app's own CSS that silently defeats `sticky`.\n *\n * `body { overflow-x: hidden }` is how most apps stop a too-wide child from\n * panning the page sideways. It also, per CSS Overflow 3, forces the computed\n * `overflow-y` to `auto` — a value the author never wrote — which makes the\n * body a **scroll container**. Every sticky descendant then pins to the body's\n * scrollport instead of the viewport, and that scrollport travels with the\n * document: measured in Chromium at 390px with a long page, the bar sat at\n * `top: -900px` after scrolling 900px, i.e. off screen.\n *\n * Nothing about that reads as a CSS problem from the app's side. The bar still\n * reports `position: sticky` in DevTools, the markup is unchanged, and on\n * desktop the screens usually fit without scrolling so the bug never shows. It\n * surfaces on Chrome Android, where the collapsing URL bar makes every screen a\n * scrolling screen — and it gets reported as \"the app bar is broken\", because\n * that is what the user sees.\n *\n * Hence this warning: the SDK cannot fix it from inside the component (a sticky\n * element has no way to opt out of its scroll container, and a rule the SDK\n * ships in its reset loses to the app's own stylesheet, which is imported\n * after), but it can name the cause in one console line.\n *\n * `clip` is the fix because it clamps the same horizontal overflow without\n * creating a scroll container. It has to be on `html` **and** `body` — with it\n * on only one of them the document still panned to `x: 500` in the same\n * measurement.\n */\nconst MESSAGE =\n \"[tempest-react-sdk] <AppBar sticky /> will not stick: `document.body` has \" +\n \"`overflow-x: hidden`, which forces its computed `overflow-y` to `auto` and makes the \" +\n \"body a scroll container. The bar then pins to the body's scrollport instead of the \" +\n \"viewport and scrolls off the top with the content — most visibly on Chrome Android. \" +\n \"Fix: `html, body { overflow-x: clip }`, on both elements, since neither clamps alone. \" +\n \"Pass `sticky={false}` if the bar is meant to scroll away.\";\n\n/** Set once the warning has been printed, so re-renders do not bury the console. */\nlet warned = false;\n\n/**\n * Reset the warn-once latch. Test-only — the latch is module state, and a suite\n * that renders more than one bar would otherwise see the warning only once.\n */\nexport function resetStickyBodyWarning(): void {\n warned = false;\n}\n\n/**\n * Warn once, in development, when the page's own CSS will keep a sticky bar\n * from sticking.\n *\n * Reads the body's `overflow-x` rather than walking the ancestors, because that\n * single declaration is the whole failure mode: an app that genuinely wants the\n * body to scroll writes `overflow-y: auto` itself, and a sticky bar inside a\n * scroll container the app chose on purpose behaves exactly as intended. What\n * is never intentional is acquiring that scroll container as a side effect of\n * clamping the other axis.\n *\n * @param enabled - Whether the bar is actually sticky. A bar rendered with\n * `sticky={false}` has nothing to lose and stays quiet.\n */\nexport function useStickyBodyWarning(enabled: boolean): void {\n useEffect(() => {\n if (!enabled || warned || !isDevBuild()) return;\n if (typeof document === \"undefined\" || !document.body) return;\n if (getComputedStyle(document.body).overflowX !== \"hidden\") return;\n warned = true;\n console.warn(MESSAGE);\n }, [enabled]);\n}\n"],"mappings":"mEAgCA,IAAM,EACF,wdAQA,EAAS,GAwBb,SAAgB,EAAqB,EAAwB,EACzD,EAAA,EAAA,UAAA,KAAgB,CACR,CAAC,GAAW,GAAU,CAAC,EAAA,WAAW,GAClC,OAAO,SAAa,KAAe,CAAC,SAAS,MAC7C,iBAAiB,SAAS,IAAI,CAAC,CAAC,YAAc,WAClD,EAAS,GACT,QAAQ,KAAK,CAAO,EACxB,EAAG,CAAC,CAAO,CAAC,CAChB"}
1
+ {"version":3,"file":"use-sticky-body-warning.cjs","names":[],"sources":["../../../src/components/AppBar/use-sticky-body-warning.ts"],"sourcesContent":["import { useEffect } from \"react\";\n\nimport { isDevBuild } from \"../../utils/dev-mode\";\n\n/**\n * The one line of the app's own CSS that silently defeats `sticky`.\n *\n * `body { overflow-x: hidden }` is how most apps stop a too-wide child from\n * panning the page sideways. It also, per CSS Overflow 3, forces the computed\n * `overflow-y` to `auto` — a value the author never wrote — which makes the\n * body a **scroll container**. Every sticky descendant then pins to the body's\n * scrollport instead of the viewport, and that scrollport travels with the\n * document: measured in Chromium at 390px with a long page, the bar sat at\n * `top: -900px` after scrolling 900px, i.e. off screen.\n *\n * Nothing about that reads as a CSS problem from the app's side. The bar still\n * reports `position: sticky` in DevTools, the markup is unchanged, and on\n * desktop the screens usually fit without scrolling so the bug never shows. It\n * surfaces on Chrome Android, where the collapsing URL bar makes every screen a\n * scrolling screen — and it gets reported as \"the app bar is broken\", because\n * that is what the user sees.\n *\n * Hence this warning: the SDK cannot fix it from inside the component (a sticky\n * element has no way to opt out of its scroll container, and a rule the SDK\n * ships in its reset loses to the app's own stylesheet, which is imported\n * after), but it can name the cause in one console line.\n *\n * `clip` is the fix because it clamps the same horizontal overflow without\n * creating a scroll container. It has to be on `html` **and** `body` — with it\n * on only one of them the document still panned to `x: 500` in the same\n * measurement.\n */\nconst MESSAGE =\n \"[tempest-react-sdk] <AppBar sticky /> will not stick: `document.body` has \" +\n \"`overflow-x: hidden`, which forces its computed `overflow-y` to `auto` and makes the \" +\n \"body a scroll container. The bar then pins to the body's scrollport instead of the \" +\n \"viewport and scrolls off the top with the content — most visibly on Chrome Android. \" +\n \"Fix: `html, body { overflow-x: clip }`, on both elements, since neither clamps alone. \" +\n \"Pass `sticky={false}` if the bar is meant to scroll away.\";\n\n/** Set once the warning has been printed, so re-renders do not bury the console. */\nlet warned = false;\n\n/**\n * Reset the warn-once latch. Test-only — the latch is module state, and a suite\n * that renders more than one bar would otherwise see the warning only once.\n */\nexport function resetStickyBodyWarning(): void {\n warned = false;\n}\n\n/**\n * Warn once, in development, when the page's own CSS will keep a sticky bar\n * from sticking.\n *\n * Reads the body's `overflow-x` rather than walking the ancestors, because that\n * single declaration is the whole failure mode: an app that genuinely wants the\n * body to scroll writes `overflow-y: auto` itself, and a sticky bar inside a\n * scroll container the app chose on purpose behaves exactly as intended. What\n * is never intentional is acquiring that scroll container as a side effect of\n * clamping the other axis.\n *\n * @param enabled - Whether the bar is actually sticky. A bar rendered with\n * `sticky={false}` has nothing to lose and stays quiet.\n */\nexport function useStickyBodyWarning(enabled: boolean): void {\n useEffect(() => {\n if (!enabled || warned || !isDevBuild()) return;\n if (typeof document === \"undefined\" || !document.body) return;\n if (getComputedStyle(document.body).overflowX !== \"hidden\") return;\n warned = true;\n console.warn(MESSAGE);\n }, [enabled]);\n}\n"],"mappings":"mEAgCA,IAAM,EACF,wdAQA,EAAS,GAwBb,SAAgB,EAAqB,EAAwB,EACzD,EAAA,EAAA,UAAA,KAAgB,CACR,CAAC,GAAW,GAAU,CAAC,EAAA,WAAW,GAClC,OAAO,SAAa,KAAe,CAAC,SAAS,MAC7C,iBAAiB,SAAS,IAAI,CAAC,CAAC,YAAc,WAClD,EAAS,GACT,QAAQ,KAAK,CAAO,EACxB,EAAG,CAAC,CAAO,CAAC,CAChB"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-sticky-body-warning.js","names":[],"sources":["../../../src/components/AppBar/use-sticky-body-warning.ts"],"sourcesContent":["import { useEffect } from \"react\";\n\nimport { isDevBuild } from \"../../utils\";\n\n/**\n * The one line of the app's own CSS that silently defeats `sticky`.\n *\n * `body { overflow-x: hidden }` is how most apps stop a too-wide child from\n * panning the page sideways. It also, per CSS Overflow 3, forces the computed\n * `overflow-y` to `auto` — a value the author never wrote — which makes the\n * body a **scroll container**. Every sticky descendant then pins to the body's\n * scrollport instead of the viewport, and that scrollport travels with the\n * document: measured in Chromium at 390px with a long page, the bar sat at\n * `top: -900px` after scrolling 900px, i.e. off screen.\n *\n * Nothing about that reads as a CSS problem from the app's side. The bar still\n * reports `position: sticky` in DevTools, the markup is unchanged, and on\n * desktop the screens usually fit without scrolling so the bug never shows. It\n * surfaces on Chrome Android, where the collapsing URL bar makes every screen a\n * scrolling screen — and it gets reported as \"the app bar is broken\", because\n * that is what the user sees.\n *\n * Hence this warning: the SDK cannot fix it from inside the component (a sticky\n * element has no way to opt out of its scroll container, and a rule the SDK\n * ships in its reset loses to the app's own stylesheet, which is imported\n * after), but it can name the cause in one console line.\n *\n * `clip` is the fix because it clamps the same horizontal overflow without\n * creating a scroll container. It has to be on `html` **and** `body` — with it\n * on only one of them the document still panned to `x: 500` in the same\n * measurement.\n */\nconst MESSAGE =\n \"[tempest-react-sdk] <AppBar sticky /> will not stick: `document.body` has \" +\n \"`overflow-x: hidden`, which forces its computed `overflow-y` to `auto` and makes the \" +\n \"body a scroll container. The bar then pins to the body's scrollport instead of the \" +\n \"viewport and scrolls off the top with the content — most visibly on Chrome Android. \" +\n \"Fix: `html, body { overflow-x: clip }`, on both elements, since neither clamps alone. \" +\n \"Pass `sticky={false}` if the bar is meant to scroll away.\";\n\n/** Set once the warning has been printed, so re-renders do not bury the console. */\nlet warned = false;\n\n/**\n * Reset the warn-once latch. Test-only — the latch is module state, and a suite\n * that renders more than one bar would otherwise see the warning only once.\n */\nexport function resetStickyBodyWarning(): void {\n warned = false;\n}\n\n/**\n * Warn once, in development, when the page's own CSS will keep a sticky bar\n * from sticking.\n *\n * Reads the body's `overflow-x` rather than walking the ancestors, because that\n * single declaration is the whole failure mode: an app that genuinely wants the\n * body to scroll writes `overflow-y: auto` itself, and a sticky bar inside a\n * scroll container the app chose on purpose behaves exactly as intended. What\n * is never intentional is acquiring that scroll container as a side effect of\n * clamping the other axis.\n *\n * @param enabled - Whether the bar is actually sticky. A bar rendered with\n * `sticky={false}` has nothing to lose and stays quiet.\n */\nexport function useStickyBodyWarning(enabled: boolean): void {\n useEffect(() => {\n if (!enabled || warned || !isDevBuild()) return;\n if (typeof document === \"undefined\" || !document.body) return;\n if (getComputedStyle(document.body).overflowX !== \"hidden\") return;\n warned = true;\n console.warn(MESSAGE);\n }, [enabled]);\n}\n"],"mappings":";;;AAgCA,IAAM,IACF,ydAQA,IAAS;AAwBb,SAAgB,EAAqB,GAAwB;CACzD,QAAgB;EACR,CAAC,KAAW,KAAU,CAAC,EAAW,KAClC,OAAO,WAAa,OAAe,CAAC,SAAS,QAC7C,iBAAiB,SAAS,IAAI,CAAC,CAAC,cAAc,aAClD,IAAS,IACT,QAAQ,KAAK,CAAO;CACxB,GAAG,CAAC,CAAO,CAAC;AAChB"}
1
+ {"version":3,"file":"use-sticky-body-warning.js","names":[],"sources":["../../../src/components/AppBar/use-sticky-body-warning.ts"],"sourcesContent":["import { useEffect } from \"react\";\n\nimport { isDevBuild } from \"../../utils/dev-mode\";\n\n/**\n * The one line of the app's own CSS that silently defeats `sticky`.\n *\n * `body { overflow-x: hidden }` is how most apps stop a too-wide child from\n * panning the page sideways. It also, per CSS Overflow 3, forces the computed\n * `overflow-y` to `auto` — a value the author never wrote — which makes the\n * body a **scroll container**. Every sticky descendant then pins to the body's\n * scrollport instead of the viewport, and that scrollport travels with the\n * document: measured in Chromium at 390px with a long page, the bar sat at\n * `top: -900px` after scrolling 900px, i.e. off screen.\n *\n * Nothing about that reads as a CSS problem from the app's side. The bar still\n * reports `position: sticky` in DevTools, the markup is unchanged, and on\n * desktop the screens usually fit without scrolling so the bug never shows. It\n * surfaces on Chrome Android, where the collapsing URL bar makes every screen a\n * scrolling screen — and it gets reported as \"the app bar is broken\", because\n * that is what the user sees.\n *\n * Hence this warning: the SDK cannot fix it from inside the component (a sticky\n * element has no way to opt out of its scroll container, and a rule the SDK\n * ships in its reset loses to the app's own stylesheet, which is imported\n * after), but it can name the cause in one console line.\n *\n * `clip` is the fix because it clamps the same horizontal overflow without\n * creating a scroll container. It has to be on `html` **and** `body` — with it\n * on only one of them the document still panned to `x: 500` in the same\n * measurement.\n */\nconst MESSAGE =\n \"[tempest-react-sdk] <AppBar sticky /> will not stick: `document.body` has \" +\n \"`overflow-x: hidden`, which forces its computed `overflow-y` to `auto` and makes the \" +\n \"body a scroll container. The bar then pins to the body's scrollport instead of the \" +\n \"viewport and scrolls off the top with the content — most visibly on Chrome Android. \" +\n \"Fix: `html, body { overflow-x: clip }`, on both elements, since neither clamps alone. \" +\n \"Pass `sticky={false}` if the bar is meant to scroll away.\";\n\n/** Set once the warning has been printed, so re-renders do not bury the console. */\nlet warned = false;\n\n/**\n * Reset the warn-once latch. Test-only — the latch is module state, and a suite\n * that renders more than one bar would otherwise see the warning only once.\n */\nexport function resetStickyBodyWarning(): void {\n warned = false;\n}\n\n/**\n * Warn once, in development, when the page's own CSS will keep a sticky bar\n * from sticking.\n *\n * Reads the body's `overflow-x` rather than walking the ancestors, because that\n * single declaration is the whole failure mode: an app that genuinely wants the\n * body to scroll writes `overflow-y: auto` itself, and a sticky bar inside a\n * scroll container the app chose on purpose behaves exactly as intended. What\n * is never intentional is acquiring that scroll container as a side effect of\n * clamping the other axis.\n *\n * @param enabled - Whether the bar is actually sticky. A bar rendered with\n * `sticky={false}` has nothing to lose and stays quiet.\n */\nexport function useStickyBodyWarning(enabled: boolean): void {\n useEffect(() => {\n if (!enabled || warned || !isDevBuild()) return;\n if (typeof document === \"undefined\" || !document.body) return;\n if (getComputedStyle(document.body).overflowX !== \"hidden\") return;\n warned = true;\n console.warn(MESSAGE);\n }, [enabled]);\n}\n"],"mappings":";;;AAgCA,IAAM,IACF,ydAQA,IAAS;AAwBb,SAAgB,EAAqB,GAAwB;CACzD,QAAgB;EACR,CAAC,KAAW,KAAU,CAAC,EAAW,KAClC,OAAO,WAAa,OAAe,CAAC,SAAS,QAC7C,iBAAiB,SAAS,IAAI,CAAC,CAAC,cAAc,aAClD,IAAS,IACT,QAAQ,KAAK,CAAO;CACxB,GAAG,CAAC,CAAO,CAAC;AAChB"}
@@ -1,2 +1,2 @@
1
- const e=require("../../utils/cn.cjs"),t=require("./bar-list-model.cjs"),n=require("./BarList.module.cjs");let r=require("react/jsx-runtime");function i({items:i,valueFormatter:a,showPercentage:o=!1,sort:s=`desc`,max:c,otherLabel:l,className:u,...d}){let f=t.buildBarListRows(i,s,c,l);return(0,r.jsx)(`ul`,{className:e.cn(n.default.list,u),...d,children:f.map(e=>(0,r.jsxs)(`li`,{className:n.default.item,children:[(0,r.jsxs)(`div`,{className:n.default.line,children:[(0,r.jsx)(`span`,{className:n.default.label,children:e.label}),(0,r.jsxs)(`span`,{className:n.default.value,children:[a?a(e.value):e.value,o&&(0,r.jsxs)(`span`,{className:n.default.percentage,children:[Math.round(e.percentage),`%`]})]})]}),(0,r.jsx)(`div`,{className:n.default.track,"aria-hidden":`true`,children:(0,r.jsx)(`div`,{className:n.default.fill,style:{width:`${e.width}%`,backgroundColor:e.color??`var(--tempest-chart-${e.index%8+1})`}})})]},`${e.label}-${e.index}`))})}exports.BarList=i;
1
+ const e=require("../../utils/cn.cjs"),t=require("../../charts/use-chart-colors.cjs"),n=require("./bar-list-model.cjs"),r=require("./BarList.module.cjs");let i=require("react"),a=require("react/jsx-runtime");function o({items:o,valueFormatter:s,showPercentage:c=!1,sort:l=`desc`,max:u,otherLabel:d,className:f,...p}){let m=(0,i.useMemo)(()=>n.buildBarListRows(o,l,u,d),[o,l,u,d]),h=t.useChartColors();return(0,a.jsx)(`ul`,{className:e.cn(r.default.list,f),...p,children:m.map(e=>(0,a.jsxs)(`li`,{className:r.default.item,children:[(0,a.jsxs)(`div`,{className:r.default.line,children:[(0,a.jsx)(`span`,{className:r.default.label,children:e.label}),(0,a.jsxs)(`span`,{className:r.default.value,children:[s?s(e.value):e.value,c&&(0,a.jsxs)(`span`,{className:r.default.percentage,children:[Math.round(e.percentage),`%`]})]})]}),(0,a.jsx)(`div`,{className:r.default.track,"aria-hidden":`true`,children:(0,a.jsx)(`div`,{className:r.default.fill,style:{width:`${e.width}%`,backgroundColor:e.color??h[e.index%h.length]}})})]},`${e.label}-${e.index}`))})}exports.BarList=o;
2
2
  //# sourceMappingURL=BarList.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"BarList.cjs","names":[],"sources":["../../../src/components/BarList/BarList.tsx"],"sourcesContent":["import type { HTMLAttributes } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { buildBarListRows, type BarListItem, type BarListSort } from \"./bar-list-model\";\nimport styles from \"./BarList.module.css\";\n\nexport type { BarListItem, BarListSort } from \"./bar-list-model\";\n\nexport interface BarListProps extends Omit<HTMLAttributes<HTMLUListElement>, \"children\"> {\n /** The rows. Entries whose value is not finite are dropped. */\n items: readonly BarListItem[];\n /** Render the number. Defaults to the value as-is. */\n valueFormatter?: (value: number) => string;\n /** Show each row's share of the total next to its value. Default `false`. */\n showPercentage?: boolean;\n /** Ordering. Default `\"desc\"`, which is what a ranking means. */\n sort?: BarListSort;\n /** Keep at most this many rows. */\n max?: number;\n /**\n * Label for one aggregated row holding everything `max` cut off.\n *\n * Without it, `max` simply truncates. The aggregate row only appears when more\n * than one row was cut — collapsing a single row into \"others\" hides its name\n * for nothing.\n */\n otherLabel?: string;\n}\n\n/**\n * A ranked distribution: label, proportional bar, value, optional share.\n *\n * The most common chart on an admin panel, and the one the SDK kept sending\n * people to write by hand — `Progress` is a single bar and `Sparkline` is a time\n * series, so a \"users per plan\" block ended up reimplemented per screen, each\n * with its own CSS and its own `.sort()`.\n *\n * It is a **list**, not a picture: `<ul>` / `<li>` with the value written as\n * text, the bar `aria-hidden` behind it. A screen reader reads \"Free, 128, 62%\"\n * because that text is there, not because an `aria-label` restates a drawing.\n * Which is also why the label never sits on top of the bar — text over a tinted\n * fill has to be re-verified against that fill, and the SDK has been caught by\n * that twice.\n *\n * Bar width is relative to the **largest** row, so the biggest bar fills the\n * track; the percentage is the row's share of the **total**. They are different\n * numbers on purpose: a width scaled by the total leaves every bar short in a\n * long list, which is when the chart is needed most.\n *\n * @example\n * <BarList\n * items={[{ label: \"Free\", value: 128 }, { label: \"Pro\", value: 32 }]}\n * valueFormatter={(n) => `${n} ativos`}\n * showPercentage\n * max={5}\n * otherLabel=\"Outros\"\n * />\n *\n * @param props - Items plus presentation.\n * @returns The list.\n */\nexport function BarList({\n items,\n valueFormatter,\n showPercentage = false,\n sort = \"desc\",\n max,\n otherLabel,\n className,\n ...rest\n}: BarListProps) {\n const rows = buildBarListRows(items, sort, max, otherLabel);\n\n return (\n <ul className={cn(styles.list, className)} {...rest}>\n {rows.map((row) => (\n <li key={`${row.label}-${row.index}`} className={styles.item}>\n <div className={styles.line}>\n <span className={styles.label}>{row.label}</span>\n <span className={styles.value}>\n {valueFormatter ? valueFormatter(row.value) : row.value}\n {showPercentage && (\n <span className={styles.percentage}>\n {Math.round(row.percentage)}%\n </span>\n )}\n </span>\n </div>\n <div className={styles.track} aria-hidden=\"true\">\n <div\n className={styles.fill}\n style={{\n width: `${row.width}%`,\n backgroundColor:\n row.color ?? `var(--tempest-chart-${(row.index % 8) + 1})`,\n }}\n />\n </div>\n </li>\n ))}\n </ul>\n );\n}\n"],"mappings":"6IA8DA,SAAgB,EAAQ,CACpB,QACA,iBACA,iBAAiB,GACjB,OAAO,OACP,MACA,aACA,YACA,GAAG,GACU,CACb,IAAM,EAAO,EAAA,iBAAiB,EAAO,EAAM,EAAK,CAAU,EAE1D,OACI,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,CAAS,EAAG,GAAI,EAC1C,SAAA,EAAK,IAAK,IACP,EAAA,EAAA,KAAA,CAAC,KAAD,CAAsC,UAAW,EAAA,QAAO,KAAxD,SAAA,EACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,EAAI,KAAY,CAAA,GAChD,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAxB,SAAA,CACK,EAAiB,EAAe,EAAI,KAAK,EAAI,EAAI,MACjD,IACG,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,WAAxB,SAAA,CACK,KAAK,MAAM,EAAI,UAAU,EAAE,GAC1B,CAER,CAAA,CAAA,CACL,CAAA,CAAA,CACL,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAO,cAAY,OACtC,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,KAClB,MAAO,CACH,MAAO,GAAG,EAAI,MAAM,GACpB,gBACI,EAAI,OAAS,uBAAwB,EAAI,MAAQ,EAAK,EAAE,EAChE,CACH,CAAA,CACA,CAAA,CACL,CAtBK,EAAA,GAAG,EAAI,MAAM,GAAG,EAAI,OAsBzB,CACP,CACD,CAAA,CAEZ"}
1
+ {"version":3,"file":"BarList.cjs","names":[],"sources":["../../../src/components/BarList/BarList.tsx"],"sourcesContent":["import { useMemo, type HTMLAttributes } from \"react\";\n\nimport { useChartColors } from \"@/charts/use-chart-colors\";\nimport { cn } from \"@/utils/cn\";\n\nimport { buildBarListRows, type BarListItem, type BarListSort } from \"./bar-list-model\";\nimport styles from \"./BarList.module.css\";\n\nexport type { BarListItem, BarListSort } from \"./bar-list-model\";\n\nexport interface BarListProps extends Omit<HTMLAttributes<HTMLUListElement>, \"children\"> {\n /** The rows. Entries whose value is not finite are dropped. */\n items: readonly BarListItem[];\n /** Render the number. Defaults to the value as-is. */\n valueFormatter?: (value: number) => string;\n /** Show each row's share of the total next to its value. Default `false`. */\n showPercentage?: boolean;\n /** Ordering. Default `\"desc\"`, which is what a ranking means. */\n sort?: BarListSort;\n /** Keep at most this many rows. */\n max?: number;\n /**\n * Label for one aggregated row holding everything `max` cut off.\n *\n * Without it, `max` simply truncates. The aggregate row only appears when more\n * than one row was cut — collapsing a single row into \"others\" hides its name\n * for nothing.\n */\n otherLabel?: string;\n}\n\n/**\n * A ranked distribution: label, proportional bar, value, optional share.\n *\n * The most common chart on an admin panel, and the one the SDK kept sending\n * people to write by hand — `Progress` is a single bar and `Sparkline` is a time\n * series, so a \"users per plan\" block ended up reimplemented per screen, each\n * with its own CSS and its own `.sort()`.\n *\n * It is a **list**, not a picture: `<ul>` / `<li>` with the value written as\n * text, the bar `aria-hidden` behind it. A screen reader reads \"Free, 128, 62%\"\n * because that text is there, not because an `aria-label` restates a drawing.\n * Which is also why the label never sits on top of the bar — text over a tinted\n * fill has to be re-verified against that fill, and the SDK has been caught by\n * that twice.\n *\n * Bar width is relative to the **largest** row, so the biggest bar fills the\n * track; the percentage is the row's share of the **total**. They are different\n * numbers on purpose: a width scaled by the total leaves every bar short in a\n * long list, which is when the chart is needed most.\n *\n * Colors come from {@link useChartColors}, the same resolver every chart in the\n * SDK uses, so a theme that declares fewer series than the eight\n * `--tempest-chart-*` slots cycles within its own palette. Reading the tokens\n * through CSS `var()` could not do that: the count lives in\n * `--tempest-chart-count`, which CSS cannot use as a modulus, so a six-color\n * brand palette got the SDK's leftover defaults in rows seven and eight — the\n * exact regression that token exists to prevent. `palette.ts` imports nothing,\n * so this pulls no chart library into the slice.\n *\n * @example\n * <BarList\n * items={[{ label: \"Free\", value: 128 }, { label: \"Pro\", value: 32 }]}\n * valueFormatter={(n) => `${n} ativos`}\n * showPercentage\n * max={5}\n * otherLabel=\"Outros\"\n * />\n *\n * @param props - Items plus presentation.\n * @returns The list.\n */\nexport function BarList({\n items,\n valueFormatter,\n showPercentage = false,\n sort = \"desc\",\n max,\n otherLabel,\n className,\n ...rest\n}: BarListProps) {\n const rows = useMemo(\n () => buildBarListRows(items, sort, max, otherLabel),\n [items, sort, max, otherLabel],\n );\n const palette = useChartColors();\n\n return (\n <ul className={cn(styles.list, className)} {...rest}>\n {rows.map((row) => (\n <li key={`${row.label}-${row.index}`} className={styles.item}>\n <div className={styles.line}>\n <span className={styles.label}>{row.label}</span>\n <span className={styles.value}>\n {valueFormatter ? valueFormatter(row.value) : row.value}\n {showPercentage && (\n <span className={styles.percentage}>\n {Math.round(row.percentage)}%\n </span>\n )}\n </span>\n </div>\n <div className={styles.track} aria-hidden=\"true\">\n <div\n className={styles.fill}\n style={{\n width: `${row.width}%`,\n backgroundColor: row.color ?? palette[row.index % palette.length],\n }}\n />\n </div>\n </li>\n ))}\n </ul>\n );\n}\n"],"mappings":"+MAwEA,SAAgB,EAAQ,CACpB,QACA,iBACA,iBAAiB,GACjB,OAAO,OACP,MACA,aACA,YACA,GAAG,GACU,CACb,IAAM,GAAA,EAAO,EAAA,QAAA,KACH,EAAA,iBAAiB,EAAO,EAAM,EAAK,CAAU,EACnD,CAAC,EAAO,EAAM,EAAK,CAAU,CACjC,EACM,EAAU,EAAA,eAAe,EAE/B,OACI,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,CAAS,EAAG,GAAI,EAC1C,SAAA,EAAK,IAAK,IACP,EAAA,EAAA,KAAA,CAAC,KAAD,CAAsC,UAAW,EAAA,QAAO,KAAxD,SAAA,EACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,EAAI,KAAY,CAAA,GAChD,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAxB,SAAA,CACK,EAAiB,EAAe,EAAI,KAAK,EAAI,EAAI,MACjD,IACG,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,WAAxB,SAAA,CACK,KAAK,MAAM,EAAI,UAAU,EAAE,GAC1B,CAER,CAAA,CAAA,CACL,CAAA,CAAA,CACL,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAO,cAAY,OACtC,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,KAClB,MAAO,CACH,MAAO,GAAG,EAAI,MAAM,GACpB,gBAAiB,EAAI,OAAS,EAAQ,EAAI,MAAQ,EAAQ,OAC9D,CACH,CAAA,CACA,CAAA,CACL,CArBK,EAAA,GAAG,EAAI,MAAM,GAAG,EAAI,OAqBzB,CACP,CACD,CAAA,CAEZ"}