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,2 +1,2 @@
1
- let e=require("react"),t=require("react/jsx-runtime");var n=(0,e.createContext)(null);function r(e){return e===`dark`||e===`light`?e:typeof window>`u`?`light`:window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}function i(e,t,n,r){let i=Array.isArray(n)?n:[n];for(let n of i)e.setAttribute(n,t);if(r&&typeof document<`u`){let e=document.querySelector(`meta[name="theme-color"]`);e&&(e.content=r[t])}}function a(e){if(!e||typeof window>`u`)return null;try{let t=window.localStorage.getItem(e);return t===`light`||t===`dark`||t===`system`?t:null}catch{return null}}function o({children:o,defaultTheme:s=`system`,storageKey:c=`tempest-theme`,target:l,attribute:u=`data-tempest-theme`,themeColor:d}){let[f,p]=(0,e.useState)(()=>a(c)??s),[m,h]=(0,e.useState)(()=>r(f)),g=(0,e.useRef)(l);(0,e.useEffect)(()=>{g.current=l},[l]);let _=Array.isArray(u)?u.join(`,`):u,v=(0,e.useRef)(d);(0,e.useEffect)(()=>{v.current=d},[d]),(0,e.useEffect)(()=>{let e=g.current?.()??document.documentElement;if(!e)return;let t=r(f);i(e,t,u,v.current),h(t)},[f,_]),(0,e.useEffect)(()=>{if(f!==`system`||typeof window>`u`)return;let e=window.matchMedia(`(prefers-color-scheme: dark)`),t=()=>{let t=g.current?.()??document.documentElement;if(!t)return;let n=e.matches?`dark`:`light`;i(t,n,u,v.current),h(n)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[f,_]);let y=(0,e.useCallback)(e=>{if(p(e),c&&typeof window<`u`)try{window.localStorage.setItem(c,e)}catch{}},[c]),b=(0,e.useCallback)(()=>{y(m===`dark`?`light`:`dark`)},[m,y]),x=(0,e.useMemo)(()=>({theme:f,resolvedTheme:m,setTheme:y,toggle:b}),[f,m,y,b]);return(0,t.jsx)(n.Provider,{value:x,children:o})}function s(){let t=(0,e.useContext)(n);if(!t)throw Error(`useTheme must be used inside a <ThemeProvider>`);return t}exports.ThemeProvider=o,exports.useTheme=s;
1
+ const e=require("../hooks/use-latest-ref.cjs");let t=require("react"),n=require("react/jsx-runtime");var r=(0,t.createContext)(null);function i(e){return e===`dark`||e===`light`?e:typeof window>`u`?`light`:window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`light`}function a(e,t,n,r){let i=Array.isArray(n)?n:[n];for(let n of i)e.setAttribute(n,t);if(r&&typeof document<`u`){let e=document.querySelector(`meta[name="theme-color"]`);e&&(e.content=r[t])}}function o(e){if(!e||typeof window>`u`)return null;try{let t=window.localStorage.getItem(e);return t===`light`||t===`dark`||t===`system`?t:null}catch{return null}}function s({children:s,defaultTheme:c=`system`,storageKey:l=`tempest-theme`,target:u,attribute:d=`data-tempest-theme`,themeColor:f}){let[p,m]=(0,t.useState)(()=>o(l)??c),[h,g]=(0,t.useState)(()=>i(p)),_=e.useLatestRef(u),v=Array.isArray(d)?d.join(`,`):d,y=e.useLatestRef(f);(0,t.useEffect)(()=>{let e=_.current?.()??document.documentElement;if(!e)return;let t=i(p);a(e,t,d,y.current),g(t)},[p,v]),(0,t.useEffect)(()=>{if(p!==`system`||typeof window>`u`)return;let e=window.matchMedia(`(prefers-color-scheme: dark)`),t=()=>{let t=_.current?.()??document.documentElement;if(!t)return;let n=e.matches?`dark`:`light`;a(t,n,d,y.current),g(n)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[p,v]);let b=(0,t.useCallback)(e=>{if(m(e),l&&typeof window<`u`)try{window.localStorage.setItem(l,e)}catch{}},[l]),x=(0,t.useCallback)(()=>{b(h===`dark`?`light`:`dark`)},[h,b]),S=(0,t.useMemo)(()=>({theme:p,resolvedTheme:h,setTheme:b,toggle:x}),[p,h,b,x]);return(0,n.jsx)(r.Provider,{value:S,children:s})}function c(){let e=(0,t.useContext)(r);if(!e)throw Error(`useTheme must be used inside a <ThemeProvider>`);return e}exports.ThemeProvider=s,exports.useTheme=c;
2
2
  //# sourceMappingURL=ThemeProvider.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.cjs","names":[],"sources":["../../src/theme/ThemeProvider.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { ResolvedTheme, ThemeMode } from \"./types\";\n\nexport interface ThemeContextValue {\n /** Raw user preference (light / dark / system). */\n theme: ThemeMode;\n /** Effective theme actually applied to the DOM (light or dark). */\n resolvedTheme: ResolvedTheme;\n /** Update the preference. Persisted to localStorage when `storageKey` is set. */\n setTheme: (next: ThemeMode) => void;\n /** Convenience: flip light ↔ dark. When in `system` mode, switches to the opposite of the current resolved theme. */\n toggle: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\nexport interface ThemeProviderProps {\n children: ReactNode;\n /** Initial preference when nothing is stored. Default: `\"system\"`. */\n defaultTheme?: ThemeMode;\n /** localStorage key used to persist the preference. Pass `null` to disable persistence. Default: `\"tempest-theme\"`. */\n storageKey?: string | null;\n /**\n * Element that receives the theme attribute(s). Defaults to\n * `document.documentElement`. Override when scoping the theme to a subtree.\n */\n target?: () => HTMLElement | null;\n /**\n * Attribute name(s) written on the target with the resolved theme\n * (`\"light\"` / `\"dark\"`). Default: `\"data-tempest-theme\"`.\n *\n * Pass an array to mirror the theme onto more than one attribute — handy\n * when the SDK components read `data-tempest-theme` but the host app's own\n * CSS keys off a different attribute (e.g. `[\"data-tempest-theme\",\n * \"data-theme\"]`). Avoids a separate sync effect in the consumer.\n */\n attribute?: string | string[];\n /**\n * When set, keeps `<meta name=\"theme-color\">` in sync with the resolved\n * theme — `content` becomes `themeColor.dark` in dark mode and\n * `themeColor.light` in light mode. The meta tag must already exist in the\n * document `<head>`. No-op when omitted.\n */\n themeColor?: { light: string; dark: string };\n}\n\nfunction resolve(mode: ThemeMode): ResolvedTheme {\n if (mode === \"dark\" || mode === \"light\") return mode;\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\n/**\n * Write the resolved theme onto every configured attribute and, when a\n * `themeColor` map is provided, sync the `<meta name=\"theme-color\">` tag.\n */\nfunction applyResolved(\n element: HTMLElement,\n resolved: ResolvedTheme,\n attribute: string | string[],\n themeColor?: { light: string; dark: string },\n): void {\n const attrs = Array.isArray(attribute) ? attribute : [attribute];\n for (const attr of attrs) element.setAttribute(attr, resolved);\n if (themeColor && typeof document !== \"undefined\") {\n const meta = document.querySelector<HTMLMetaElement>('meta[name=\"theme-color\"]');\n if (meta) meta.content = themeColor[resolved];\n }\n}\n\nfunction readStored(storageKey: string | null): ThemeMode | null {\n if (!storageKey || typeof window === \"undefined\") return null;\n try {\n const value = window.localStorage.getItem(storageKey);\n if (value === \"light\" || value === \"dark\" || value === \"system\") return value;\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Wire dark/light theming. Writes a data attribute on a target element (the\n * `<html>` element by default) and exposes the current preference via\n * {@link useTheme}.\n *\n * Pair with `themeInitScript()` in the HTML head to prevent the flash of\n * incorrect theme on first paint.\n *\n * @tempest-limits empty-catch — the theme is applied to the DOM before it is\n * persisted, so a `localStorage` write refused by quota or private mode leaves the\n * user with the theme they just picked and only forfeits it on the next load.\n * Throwing from the setter would break the switch that already worked.\n */\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"tempest-theme\",\n target,\n attribute = \"data-tempest-theme\",\n themeColor,\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<ThemeMode>(\n () => readStored(storageKey) ?? defaultTheme,\n );\n const [resolvedTheme, setResolvedTheme] = useState<ResolvedTheme>(() => resolve(theme));\n\n const targetRef = useRef<typeof target>(target);\n useEffect(() => {\n targetRef.current = target;\n }, [target]);\n\n const attributeKey = Array.isArray(attribute) ? attribute.join(\",\") : attribute;\n const themeColorRef = useRef(themeColor);\n useEffect(() => {\n themeColorRef.current = themeColor;\n }, [themeColor]);\n\n useEffect(() => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next = resolve(theme);\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n // attributeKey is the stable string form of `attribute`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n useEffect(() => {\n if (theme !== \"system\" || typeof window === \"undefined\") return;\n const list = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (): void => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next: ResolvedTheme = list.matches ? \"dark\" : \"light\";\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n };\n list.addEventListener(\"change\", handler);\n return () => list.removeEventListener(\"change\", handler);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n const setTheme = useCallback(\n (next: ThemeMode) => {\n setThemeState(next);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(storageKey, next);\n } catch {\n /* empty */\n }\n }\n },\n [storageKey],\n );\n\n const toggle = useCallback(() => {\n setTheme(resolvedTheme === \"dark\" ? \"light\" : \"dark\");\n }, [resolvedTheme, setTheme]);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, resolvedTheme, setTheme, toggle }),\n [theme, resolvedTheme, setTheme, toggle],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\n/**\n * Read and mutate the current theme. Must be used inside a {@link ThemeProvider}.\n */\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error(\"useTheme must be used inside a <ThemeProvider>\");\n return ctx;\n}\n"],"mappings":"sDAuBA,IAAM,GAAA,EAAe,EAAA,cAAA,CAAwC,IAAI,EAgCjE,SAAS,EAAQ,EAAgC,CAG7C,OAFI,IAAS,QAAU,IAAS,QAAgB,EAC5C,OAAO,OAAW,IAAoB,QACnC,OAAO,WAAW,8BAA8B,CAAC,CAAC,QAAU,OAAS,OAChF,CAMA,SAAS,EACL,EACA,EACA,EACA,EACI,CACJ,IAAM,EAAQ,MAAM,QAAQ,CAAS,EAAI,EAAY,CAAC,CAAS,EAC/D,IAAK,IAAM,KAAQ,EAAO,EAAQ,aAAa,EAAM,CAAQ,EAC7D,GAAI,GAAc,OAAO,SAAa,IAAa,CAC/C,IAAM,EAAO,SAAS,cAA+B,0BAA0B,EAC3E,IAAM,EAAK,QAAU,EAAW,GACxC,CACJ,CAEA,SAAS,EAAW,EAA6C,CAC7D,GAAI,CAAC,GAAc,OAAO,OAAW,IAAa,OAAO,KACzD,GAAI,CACA,IAAM,EAAQ,OAAO,aAAa,QAAQ,CAAU,EAEpD,OADI,IAAU,SAAW,IAAU,QAAU,IAAU,SAAiB,EACjE,IACX,MAAQ,CACJ,OAAO,IACX,CACJ,CAeA,SAAgB,EAAc,CAC1B,WACA,eAAe,SACf,aAAa,gBACb,SACA,YAAY,qBACZ,cACmB,CACnB,GAAM,CAAC,EAAO,IAAA,EAAiB,EAAA,SAAA,KACrB,EAAW,CAAU,GAAK,CACpC,EACM,CAAC,EAAe,IAAA,EAAoB,EAAA,SAAA,KAA8B,EAAQ,CAAK,CAAC,EAEhF,GAAA,EAAY,EAAA,OAAA,CAAsB,CAAM,GAC9C,EAAA,EAAA,UAAA,KAAgB,CACZ,EAAU,QAAU,CACxB,EAAG,CAAC,CAAM,CAAC,EAEX,IAAM,EAAe,MAAM,QAAQ,CAAS,EAAI,EAAU,KAAK,GAAG,EAAI,EAChE,GAAA,EAAgB,EAAA,OAAA,CAAO,CAAU,GACvC,EAAA,EAAA,UAAA,KAAgB,CACZ,EAAc,QAAU,CAC5B,EAAG,CAAC,CAAU,CAAC,GAEf,EAAA,EAAA,UAAA,KAAgB,CACZ,IAAM,EAAU,EAAU,UAAU,GAAK,SAAS,gBAClD,GAAI,CAAC,EAAS,OACd,IAAM,EAAO,EAAQ,CAAK,EAC1B,EAAc,EAAS,EAAM,EAAW,EAAc,OAAO,EAC7D,EAAiB,CAAI,CAGzB,EAAG,CAAC,EAAO,CAAY,CAAC,GAExB,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,IAAU,UAAY,OAAO,OAAW,IAAa,OACzD,IAAM,EAAO,OAAO,WAAW,8BAA8B,EACvD,MAAsB,CACxB,IAAM,EAAU,EAAU,UAAU,GAAK,SAAS,gBAClD,GAAI,CAAC,EAAS,OACd,IAAM,EAAsB,EAAK,QAAU,OAAS,QACpD,EAAc,EAAS,EAAM,EAAW,EAAc,OAAO,EAC7D,EAAiB,CAAI,CACzB,EAEA,OADA,EAAK,iBAAiB,SAAU,CAAO,MAC1B,EAAK,oBAAoB,SAAU,CAAO,CAE3D,EAAG,CAAC,EAAO,CAAY,CAAC,EAExB,IAAM,GAAA,EAAW,EAAA,YAAA,CACZ,GAAoB,CAEjB,GADA,EAAc,CAAI,EACd,GAAc,OAAO,OAAW,IAChC,GAAI,CACA,OAAO,aAAa,QAAQ,EAAY,CAAI,CAChD,MAAQ,CAER,CAER,EACA,CAAC,CAAU,CACf,EAEM,GAAA,EAAS,EAAA,YAAA,KAAkB,CAC7B,EAAS,IAAkB,OAAS,QAAU,MAAM,CACxD,EAAG,CAAC,EAAe,CAAQ,CAAC,EAEtB,GAAA,EAAQ,EAAA,QAAA,MACH,CAAE,QAAO,gBAAe,WAAU,QAAO,GAChD,CAAC,EAAO,EAAe,EAAU,CAAM,CAC3C,EAEA,OAAO,EAAA,EAAA,IAAA,CAAC,EAAa,SAAd,CAA8B,QAAQ,UAAgC,CAAA,CACjF,CAKA,SAAgB,GAA8B,CAC1C,IAAM,GAAA,EAAM,EAAA,WAAA,CAAW,CAAY,EACnC,GAAI,CAAC,EAAK,MAAU,MAAM,gDAAgD,EAC1E,OAAO,CACX"}
1
+ {"version":3,"file":"ThemeProvider.cjs","names":[],"sources":["../../src/theme/ThemeProvider.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useLatestRef } from \"@/hooks/use-latest-ref\";\nimport type { ResolvedTheme, ThemeMode } from \"./types\";\n\nexport interface ThemeContextValue {\n /** Raw user preference (light / dark / system). */\n theme: ThemeMode;\n /** Effective theme actually applied to the DOM (light or dark). */\n resolvedTheme: ResolvedTheme;\n /** Update the preference. Persisted to localStorage when `storageKey` is set. */\n setTheme: (next: ThemeMode) => void;\n /** Convenience: flip light ↔ dark. When in `system` mode, switches to the opposite of the current resolved theme. */\n toggle: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\nexport interface ThemeProviderProps {\n children: ReactNode;\n /** Initial preference when nothing is stored. Default: `\"system\"`. */\n defaultTheme?: ThemeMode;\n /** localStorage key used to persist the preference. Pass `null` to disable persistence. Default: `\"tempest-theme\"`. */\n storageKey?: string | null;\n /**\n * Element that receives the theme attribute(s). Defaults to\n * `document.documentElement`. Override when scoping the theme to a subtree.\n */\n target?: () => HTMLElement | null;\n /**\n * Attribute name(s) written on the target with the resolved theme\n * (`\"light\"` / `\"dark\"`). Default: `\"data-tempest-theme\"`.\n *\n * Pass an array to mirror the theme onto more than one attribute — handy\n * when the SDK components read `data-tempest-theme` but the host app's own\n * CSS keys off a different attribute (e.g. `[\"data-tempest-theme\",\n * \"data-theme\"]`). Avoids a separate sync effect in the consumer.\n */\n attribute?: string | string[];\n /**\n * When set, keeps `<meta name=\"theme-color\">` in sync with the resolved\n * theme — `content` becomes `themeColor.dark` in dark mode and\n * `themeColor.light` in light mode. The meta tag must already exist in the\n * document `<head>`. No-op when omitted.\n */\n themeColor?: { light: string; dark: string };\n}\n\nfunction resolve(mode: ThemeMode): ResolvedTheme {\n if (mode === \"dark\" || mode === \"light\") return mode;\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\n/**\n * Write the resolved theme onto every configured attribute and, when a\n * `themeColor` map is provided, sync the `<meta name=\"theme-color\">` tag.\n */\nfunction applyResolved(\n element: HTMLElement,\n resolved: ResolvedTheme,\n attribute: string | string[],\n themeColor?: { light: string; dark: string },\n): void {\n const attrs = Array.isArray(attribute) ? attribute : [attribute];\n for (const attr of attrs) element.setAttribute(attr, resolved);\n if (themeColor && typeof document !== \"undefined\") {\n const meta = document.querySelector<HTMLMetaElement>('meta[name=\"theme-color\"]');\n if (meta) meta.content = themeColor[resolved];\n }\n}\n\nfunction readStored(storageKey: string | null): ThemeMode | null {\n if (!storageKey || typeof window === \"undefined\") return null;\n try {\n const value = window.localStorage.getItem(storageKey);\n if (value === \"light\" || value === \"dark\" || value === \"system\") return value;\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Wire dark/light theming. Writes a data attribute on a target element (the\n * `<html>` element by default) and exposes the current preference via\n * {@link useTheme}.\n *\n * Pair with `themeInitScript()` in the HTML head to prevent the flash of\n * incorrect theme on first paint.\n *\n * @tempest-limits empty-catch — the theme is applied to the DOM before it is\n * persisted, so a `localStorage` write refused by quota or private mode leaves the\n * user with the theme they just picked and only forfeits it on the next load.\n * Throwing from the setter would break the switch that already worked.\n */\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"tempest-theme\",\n target,\n attribute = \"data-tempest-theme\",\n themeColor,\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<ThemeMode>(\n () => readStored(storageKey) ?? defaultTheme,\n );\n const [resolvedTheme, setResolvedTheme] = useState<ResolvedTheme>(() => resolve(theme));\n\n const targetRef = useLatestRef(target);\n\n const attributeKey = Array.isArray(attribute) ? attribute.join(\",\") : attribute;\n const themeColorRef = useLatestRef(themeColor);\n\n useEffect(() => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next = resolve(theme);\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n // attributeKey is the stable string form of `attribute`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n useEffect(() => {\n if (theme !== \"system\" || typeof window === \"undefined\") return;\n const list = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (): void => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next: ResolvedTheme = list.matches ? \"dark\" : \"light\";\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n };\n list.addEventListener(\"change\", handler);\n return () => list.removeEventListener(\"change\", handler);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n const setTheme = useCallback(\n (next: ThemeMode) => {\n setThemeState(next);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(storageKey, next);\n } catch {\n /* empty */\n }\n }\n },\n [storageKey],\n );\n\n const toggle = useCallback(() => {\n setTheme(resolvedTheme === \"dark\" ? \"light\" : \"dark\");\n }, [resolvedTheme, setTheme]);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, resolvedTheme, setTheme, toggle }),\n [theme, resolvedTheme, setTheme, toggle],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\n/**\n * Read and mutate the current theme. Must be used inside a {@link ThemeProvider}.\n */\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error(\"useTheme must be used inside a <ThemeProvider>\");\n return ctx;\n}\n"],"mappings":"qGAgBA,IAAM,GAAA,EAAe,EAAA,cAAA,CAAwC,IAAI,EAgCjE,SAAS,EAAQ,EAAgC,CAG7C,OAFI,IAAS,QAAU,IAAS,QAAgB,EAC5C,OAAO,OAAW,IAAoB,QACnC,OAAO,WAAW,8BAA8B,CAAC,CAAC,QAAU,OAAS,OAChF,CAMA,SAAS,EACL,EACA,EACA,EACA,EACI,CACJ,IAAM,EAAQ,MAAM,QAAQ,CAAS,EAAI,EAAY,CAAC,CAAS,EAC/D,IAAK,IAAM,KAAQ,EAAO,EAAQ,aAAa,EAAM,CAAQ,EAC7D,GAAI,GAAc,OAAO,SAAa,IAAa,CAC/C,IAAM,EAAO,SAAS,cAA+B,0BAA0B,EAC3E,IAAM,EAAK,QAAU,EAAW,GACxC,CACJ,CAEA,SAAS,EAAW,EAA6C,CAC7D,GAAI,CAAC,GAAc,OAAO,OAAW,IAAa,OAAO,KACzD,GAAI,CACA,IAAM,EAAQ,OAAO,aAAa,QAAQ,CAAU,EAEpD,OADI,IAAU,SAAW,IAAU,QAAU,IAAU,SAAiB,EACjE,IACX,MAAQ,CACJ,OAAO,IACX,CACJ,CAeA,SAAgB,EAAc,CAC1B,WACA,eAAe,SACf,aAAa,gBACb,SACA,YAAY,qBACZ,cACmB,CACnB,GAAM,CAAC,EAAO,IAAA,EAAiB,EAAA,SAAA,KACrB,EAAW,CAAU,GAAK,CACpC,EACM,CAAC,EAAe,IAAA,EAAoB,EAAA,SAAA,KAA8B,EAAQ,CAAK,CAAC,EAEhF,EAAY,EAAA,aAAa,CAAM,EAE/B,EAAe,MAAM,QAAQ,CAAS,EAAI,EAAU,KAAK,GAAG,EAAI,EAChE,EAAgB,EAAA,aAAa,CAAU,GAE7C,EAAA,EAAA,UAAA,KAAgB,CACZ,IAAM,EAAU,EAAU,UAAU,GAAK,SAAS,gBAClD,GAAI,CAAC,EAAS,OACd,IAAM,EAAO,EAAQ,CAAK,EAC1B,EAAc,EAAS,EAAM,EAAW,EAAc,OAAO,EAC7D,EAAiB,CAAI,CAGzB,EAAG,CAAC,EAAO,CAAY,CAAC,GAExB,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,IAAU,UAAY,OAAO,OAAW,IAAa,OACzD,IAAM,EAAO,OAAO,WAAW,8BAA8B,EACvD,MAAsB,CACxB,IAAM,EAAU,EAAU,UAAU,GAAK,SAAS,gBAClD,GAAI,CAAC,EAAS,OACd,IAAM,EAAsB,EAAK,QAAU,OAAS,QACpD,EAAc,EAAS,EAAM,EAAW,EAAc,OAAO,EAC7D,EAAiB,CAAI,CACzB,EAEA,OADA,EAAK,iBAAiB,SAAU,CAAO,MAC1B,EAAK,oBAAoB,SAAU,CAAO,CAE3D,EAAG,CAAC,EAAO,CAAY,CAAC,EAExB,IAAM,GAAA,EAAW,EAAA,YAAA,CACZ,GAAoB,CAEjB,GADA,EAAc,CAAI,EACd,GAAc,OAAO,OAAW,IAChC,GAAI,CACA,OAAO,aAAa,QAAQ,EAAY,CAAI,CAChD,MAAQ,CAER,CAER,EACA,CAAC,CAAU,CACf,EAEM,GAAA,EAAS,EAAA,YAAA,KAAkB,CAC7B,EAAS,IAAkB,OAAS,QAAU,MAAM,CACxD,EAAG,CAAC,EAAe,CAAQ,CAAC,EAEtB,GAAA,EAAQ,EAAA,QAAA,MACH,CAAE,QAAO,gBAAe,WAAU,QAAO,GAChD,CAAC,EAAO,EAAe,EAAU,CAAM,CAC3C,EAEA,OAAO,EAAA,EAAA,IAAA,CAAC,EAAa,SAAd,CAA8B,QAAQ,UAAgC,CAAA,CACjF,CAKA,SAAgB,GAA8B,CAC1C,IAAM,GAAA,EAAM,EAAA,WAAA,CAAW,CAAY,EACnC,GAAI,CAAC,EAAK,MAAU,MAAM,gDAAgD,EAC1E,OAAO,CACX"}
@@ -1,7 +1,8 @@
1
- import { createContext as e, useCallback as t, useContext as n, useEffect as r, useMemo as i, useRef as a, useState as o } from "react";
1
+ import { useLatestRef as e } from "../hooks/use-latest-ref.js";
2
+ import { createContext as t, useCallback as n, useContext as r, useEffect as i, useMemo as a, useState as o } from "react";
2
3
  import { jsx as s } from "react/jsx-runtime";
3
4
  //#region src/theme/ThemeProvider.tsx
4
- var c = e(null);
5
+ var c = t(null);
5
6
  function l(e) {
6
7
  return e === "dark" || e === "light" ? e : typeof window > "u" ? "light" : window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
7
8
  }
@@ -22,20 +23,14 @@ function d(e) {
22
23
  return null;
23
24
  }
24
25
  }
25
- function f({ children: e, defaultTheme: n = "system", storageKey: f = "tempest-theme", target: p, attribute: m = "data-tempest-theme", themeColor: h }) {
26
- let [g, _] = o(() => d(f) ?? n), [v, y] = o(() => l(g)), b = a(p);
27
- r(() => {
28
- b.current = p;
29
- }, [p]);
30
- let x = Array.isArray(m) ? m.join(",") : m, S = a(h);
31
- r(() => {
32
- S.current = h;
33
- }, [h]), r(() => {
26
+ function f({ children: t, defaultTheme: r = "system", storageKey: f = "tempest-theme", target: p, attribute: m = "data-tempest-theme", themeColor: h }) {
27
+ let [g, _] = o(() => d(f) ?? r), [v, y] = o(() => l(g)), b = e(p), x = Array.isArray(m) ? m.join(",") : m, S = e(h);
28
+ i(() => {
34
29
  let e = b.current?.() ?? document.documentElement;
35
30
  if (!e) return;
36
31
  let t = l(g);
37
32
  u(e, t, m, S.current), y(t);
38
- }, [g, x]), r(() => {
33
+ }, [g, x]), i(() => {
39
34
  if (g !== "system" || typeof window > "u") return;
40
35
  let e = window.matchMedia("(prefers-color-scheme: dark)"), t = () => {
41
36
  let t = b.current?.() ?? document.documentElement;
@@ -45,13 +40,13 @@ function f({ children: e, defaultTheme: n = "system", storageKey: f = "tempest-t
45
40
  };
46
41
  return e.addEventListener("change", t), () => e.removeEventListener("change", t);
47
42
  }, [g, x]);
48
- let C = t((e) => {
43
+ let C = n((e) => {
49
44
  if (_(e), f && typeof window < "u") try {
50
45
  window.localStorage.setItem(f, e);
51
46
  } catch {}
52
- }, [f]), w = t(() => {
47
+ }, [f]), w = n(() => {
53
48
  C(v === "dark" ? "light" : "dark");
54
- }, [v, C]), T = i(() => ({
49
+ }, [v, C]), T = a(() => ({
55
50
  theme: g,
56
51
  resolvedTheme: v,
57
52
  setTheme: C,
@@ -64,11 +59,11 @@ function f({ children: e, defaultTheme: n = "system", storageKey: f = "tempest-t
64
59
  ]);
65
60
  return /* @__PURE__ */ s(c.Provider, {
66
61
  value: T,
67
- children: e
62
+ children: t
68
63
  });
69
64
  }
70
65
  function p() {
71
- let e = n(c);
66
+ let e = r(c);
72
67
  if (!e) throw Error("useTheme must be used inside a <ThemeProvider>");
73
68
  return e;
74
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.js","names":[],"sources":["../../src/theme/ThemeProvider.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { ResolvedTheme, ThemeMode } from \"./types\";\n\nexport interface ThemeContextValue {\n /** Raw user preference (light / dark / system). */\n theme: ThemeMode;\n /** Effective theme actually applied to the DOM (light or dark). */\n resolvedTheme: ResolvedTheme;\n /** Update the preference. Persisted to localStorage when `storageKey` is set. */\n setTheme: (next: ThemeMode) => void;\n /** Convenience: flip light ↔ dark. When in `system` mode, switches to the opposite of the current resolved theme. */\n toggle: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\nexport interface ThemeProviderProps {\n children: ReactNode;\n /** Initial preference when nothing is stored. Default: `\"system\"`. */\n defaultTheme?: ThemeMode;\n /** localStorage key used to persist the preference. Pass `null` to disable persistence. Default: `\"tempest-theme\"`. */\n storageKey?: string | null;\n /**\n * Element that receives the theme attribute(s). Defaults to\n * `document.documentElement`. Override when scoping the theme to a subtree.\n */\n target?: () => HTMLElement | null;\n /**\n * Attribute name(s) written on the target with the resolved theme\n * (`\"light\"` / `\"dark\"`). Default: `\"data-tempest-theme\"`.\n *\n * Pass an array to mirror the theme onto more than one attribute — handy\n * when the SDK components read `data-tempest-theme` but the host app's own\n * CSS keys off a different attribute (e.g. `[\"data-tempest-theme\",\n * \"data-theme\"]`). Avoids a separate sync effect in the consumer.\n */\n attribute?: string | string[];\n /**\n * When set, keeps `<meta name=\"theme-color\">` in sync with the resolved\n * theme — `content` becomes `themeColor.dark` in dark mode and\n * `themeColor.light` in light mode. The meta tag must already exist in the\n * document `<head>`. No-op when omitted.\n */\n themeColor?: { light: string; dark: string };\n}\n\nfunction resolve(mode: ThemeMode): ResolvedTheme {\n if (mode === \"dark\" || mode === \"light\") return mode;\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\n/**\n * Write the resolved theme onto every configured attribute and, when a\n * `themeColor` map is provided, sync the `<meta name=\"theme-color\">` tag.\n */\nfunction applyResolved(\n element: HTMLElement,\n resolved: ResolvedTheme,\n attribute: string | string[],\n themeColor?: { light: string; dark: string },\n): void {\n const attrs = Array.isArray(attribute) ? attribute : [attribute];\n for (const attr of attrs) element.setAttribute(attr, resolved);\n if (themeColor && typeof document !== \"undefined\") {\n const meta = document.querySelector<HTMLMetaElement>('meta[name=\"theme-color\"]');\n if (meta) meta.content = themeColor[resolved];\n }\n}\n\nfunction readStored(storageKey: string | null): ThemeMode | null {\n if (!storageKey || typeof window === \"undefined\") return null;\n try {\n const value = window.localStorage.getItem(storageKey);\n if (value === \"light\" || value === \"dark\" || value === \"system\") return value;\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Wire dark/light theming. Writes a data attribute on a target element (the\n * `<html>` element by default) and exposes the current preference via\n * {@link useTheme}.\n *\n * Pair with `themeInitScript()` in the HTML head to prevent the flash of\n * incorrect theme on first paint.\n *\n * @tempest-limits empty-catch — the theme is applied to the DOM before it is\n * persisted, so a `localStorage` write refused by quota or private mode leaves the\n * user with the theme they just picked and only forfeits it on the next load.\n * Throwing from the setter would break the switch that already worked.\n */\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"tempest-theme\",\n target,\n attribute = \"data-tempest-theme\",\n themeColor,\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<ThemeMode>(\n () => readStored(storageKey) ?? defaultTheme,\n );\n const [resolvedTheme, setResolvedTheme] = useState<ResolvedTheme>(() => resolve(theme));\n\n const targetRef = useRef<typeof target>(target);\n useEffect(() => {\n targetRef.current = target;\n }, [target]);\n\n const attributeKey = Array.isArray(attribute) ? attribute.join(\",\") : attribute;\n const themeColorRef = useRef(themeColor);\n useEffect(() => {\n themeColorRef.current = themeColor;\n }, [themeColor]);\n\n useEffect(() => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next = resolve(theme);\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n // attributeKey is the stable string form of `attribute`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n useEffect(() => {\n if (theme !== \"system\" || typeof window === \"undefined\") return;\n const list = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (): void => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next: ResolvedTheme = list.matches ? \"dark\" : \"light\";\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n };\n list.addEventListener(\"change\", handler);\n return () => list.removeEventListener(\"change\", handler);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n const setTheme = useCallback(\n (next: ThemeMode) => {\n setThemeState(next);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(storageKey, next);\n } catch {\n /* empty */\n }\n }\n },\n [storageKey],\n );\n\n const toggle = useCallback(() => {\n setTheme(resolvedTheme === \"dark\" ? \"light\" : \"dark\");\n }, [resolvedTheme, setTheme]);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, resolvedTheme, setTheme, toggle }),\n [theme, resolvedTheme, setTheme, toggle],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\n/**\n * Read and mutate the current theme. Must be used inside a {@link ThemeProvider}.\n */\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error(\"useTheme must be used inside a <ThemeProvider>\");\n return ctx;\n}\n"],"mappings":";;;AAuBA,IAAM,IAAe,EAAwC,IAAI;AAgCjE,SAAS,EAAQ,GAAgC;CAG7C,OAFI,MAAS,UAAU,MAAS,UAAgB,IAC5C,OAAO,SAAW,MAAoB,UACnC,OAAO,WAAW,8BAA8B,CAAC,CAAC,UAAU,SAAS;AAChF;AAMA,SAAS,EACL,GACA,GACA,GACA,GACI;CACJ,IAAM,IAAQ,MAAM,QAAQ,CAAS,IAAI,IAAY,CAAC,CAAS;CAC/D,KAAK,IAAM,KAAQ,GAAO,EAAQ,aAAa,GAAM,CAAQ;CAC7D,IAAI,KAAc,OAAO,WAAa,KAAa;EAC/C,IAAM,IAAO,SAAS,cAA+B,4BAA0B;EAC/E,AAAI,MAAM,EAAK,UAAU,EAAW;CACxC;AACJ;AAEA,SAAS,EAAW,GAA6C;CAC7D,IAAI,CAAC,KAAc,OAAO,SAAW,KAAa,OAAO;CACzD,IAAI;EACA,IAAM,IAAQ,OAAO,aAAa,QAAQ,CAAU;EAEpD,OADI,MAAU,WAAW,MAAU,UAAU,MAAU,WAAiB,IACjE;CACX,QAAQ;EACJ,OAAO;CACX;AACJ;AAeA,SAAgB,EAAc,EAC1B,aACA,kBAAe,UACf,gBAAa,iBACb,WACA,eAAY,sBACZ,iBACmB;CACnB,IAAM,CAAC,GAAO,KAAiB,QACrB,EAAW,CAAU,KAAK,CACpC,GACM,CAAC,GAAe,KAAoB,QAA8B,EAAQ,CAAK,CAAC,GAEhF,IAAY,EAAsB,CAAM;CAC9C,QAAgB;EACZ,EAAU,UAAU;CACxB,GAAG,CAAC,CAAM,CAAC;CAEX,IAAM,IAAe,MAAM,QAAQ,CAAS,IAAI,EAAU,KAAK,GAAG,IAAI,GAChE,IAAgB,EAAO,CAAU;CAevC,AAdA,QAAgB;EACZ,EAAc,UAAU;CAC5B,GAAG,CAAC,CAAU,CAAC,GAEf,QAAgB;EACZ,IAAM,IAAU,EAAU,UAAU,KAAK,SAAS;EAClD,IAAI,CAAC,GAAS;EACd,IAAM,IAAO,EAAQ,CAAK;EAE1B,AADA,EAAc,GAAS,GAAM,GAAW,EAAc,OAAO,GAC7D,EAAiB,CAAI;CAGzB,GAAG,CAAC,GAAO,CAAY,CAAC,GAExB,QAAgB;EACZ,IAAI,MAAU,YAAY,OAAO,SAAW,KAAa;EACzD,IAAM,IAAO,OAAO,WAAW,8BAA8B,GACvD,UAAsB;GACxB,IAAM,IAAU,EAAU,UAAU,KAAK,SAAS;GAClD,IAAI,CAAC,GAAS;GACd,IAAM,IAAsB,EAAK,UAAU,SAAS;GAEpD,AADA,EAAc,GAAS,GAAM,GAAW,EAAc,OAAO,GAC7D,EAAiB,CAAI;EACzB;EAEA,OADA,EAAK,iBAAiB,UAAU,CAAO,SAC1B,EAAK,oBAAoB,UAAU,CAAO;CAE3D,GAAG,CAAC,GAAO,CAAY,CAAC;CAExB,IAAM,IAAW,GACZ,MAAoB;EAEjB,IADA,EAAc,CAAI,GACd,KAAc,OAAO,SAAW,KAChC,IAAI;GACA,OAAO,aAAa,QAAQ,GAAY,CAAI;EAChD,QAAQ,CAER;CAER,GACA,CAAC,CAAU,CACf,GAEM,IAAS,QAAkB;EAC7B,EAAS,MAAkB,SAAS,UAAU,MAAM;CACxD,GAAG,CAAC,GAAe,CAAQ,CAAC,GAEtB,IAAQ,SACH;EAAE;EAAO;EAAe;EAAU;CAAO,IAChD;EAAC;EAAO;EAAe;EAAU;CAAM,CAC3C;CAEA,OAAO,kBAAC,EAAa,UAAd;EAA8B;EAAQ;CAAgC,CAAA;AACjF;AAKA,SAAgB,IAA8B;CAC1C,IAAM,IAAM,EAAW,CAAY;CACnC,IAAI,CAAC,GAAK,MAAU,MAAM,gDAAgD;CAC1E,OAAO;AACX"}
1
+ {"version":3,"file":"ThemeProvider.js","names":[],"sources":["../../src/theme/ThemeProvider.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useLatestRef } from \"@/hooks/use-latest-ref\";\nimport type { ResolvedTheme, ThemeMode } from \"./types\";\n\nexport interface ThemeContextValue {\n /** Raw user preference (light / dark / system). */\n theme: ThemeMode;\n /** Effective theme actually applied to the DOM (light or dark). */\n resolvedTheme: ResolvedTheme;\n /** Update the preference. Persisted to localStorage when `storageKey` is set. */\n setTheme: (next: ThemeMode) => void;\n /** Convenience: flip light ↔ dark. When in `system` mode, switches to the opposite of the current resolved theme. */\n toggle: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\nexport interface ThemeProviderProps {\n children: ReactNode;\n /** Initial preference when nothing is stored. Default: `\"system\"`. */\n defaultTheme?: ThemeMode;\n /** localStorage key used to persist the preference. Pass `null` to disable persistence. Default: `\"tempest-theme\"`. */\n storageKey?: string | null;\n /**\n * Element that receives the theme attribute(s). Defaults to\n * `document.documentElement`. Override when scoping the theme to a subtree.\n */\n target?: () => HTMLElement | null;\n /**\n * Attribute name(s) written on the target with the resolved theme\n * (`\"light\"` / `\"dark\"`). Default: `\"data-tempest-theme\"`.\n *\n * Pass an array to mirror the theme onto more than one attribute — handy\n * when the SDK components read `data-tempest-theme` but the host app's own\n * CSS keys off a different attribute (e.g. `[\"data-tempest-theme\",\n * \"data-theme\"]`). Avoids a separate sync effect in the consumer.\n */\n attribute?: string | string[];\n /**\n * When set, keeps `<meta name=\"theme-color\">` in sync with the resolved\n * theme — `content` becomes `themeColor.dark` in dark mode and\n * `themeColor.light` in light mode. The meta tag must already exist in the\n * document `<head>`. No-op when omitted.\n */\n themeColor?: { light: string; dark: string };\n}\n\nfunction resolve(mode: ThemeMode): ResolvedTheme {\n if (mode === \"dark\" || mode === \"light\") return mode;\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\n/**\n * Write the resolved theme onto every configured attribute and, when a\n * `themeColor` map is provided, sync the `<meta name=\"theme-color\">` tag.\n */\nfunction applyResolved(\n element: HTMLElement,\n resolved: ResolvedTheme,\n attribute: string | string[],\n themeColor?: { light: string; dark: string },\n): void {\n const attrs = Array.isArray(attribute) ? attribute : [attribute];\n for (const attr of attrs) element.setAttribute(attr, resolved);\n if (themeColor && typeof document !== \"undefined\") {\n const meta = document.querySelector<HTMLMetaElement>('meta[name=\"theme-color\"]');\n if (meta) meta.content = themeColor[resolved];\n }\n}\n\nfunction readStored(storageKey: string | null): ThemeMode | null {\n if (!storageKey || typeof window === \"undefined\") return null;\n try {\n const value = window.localStorage.getItem(storageKey);\n if (value === \"light\" || value === \"dark\" || value === \"system\") return value;\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Wire dark/light theming. Writes a data attribute on a target element (the\n * `<html>` element by default) and exposes the current preference via\n * {@link useTheme}.\n *\n * Pair with `themeInitScript()` in the HTML head to prevent the flash of\n * incorrect theme on first paint.\n *\n * @tempest-limits empty-catch — the theme is applied to the DOM before it is\n * persisted, so a `localStorage` write refused by quota or private mode leaves the\n * user with the theme they just picked and only forfeits it on the next load.\n * Throwing from the setter would break the switch that already worked.\n */\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"tempest-theme\",\n target,\n attribute = \"data-tempest-theme\",\n themeColor,\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<ThemeMode>(\n () => readStored(storageKey) ?? defaultTheme,\n );\n const [resolvedTheme, setResolvedTheme] = useState<ResolvedTheme>(() => resolve(theme));\n\n const targetRef = useLatestRef(target);\n\n const attributeKey = Array.isArray(attribute) ? attribute.join(\",\") : attribute;\n const themeColorRef = useLatestRef(themeColor);\n\n useEffect(() => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next = resolve(theme);\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n // attributeKey is the stable string form of `attribute`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n useEffect(() => {\n if (theme !== \"system\" || typeof window === \"undefined\") return;\n const list = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (): void => {\n const element = targetRef.current?.() ?? document.documentElement;\n if (!element) return;\n const next: ResolvedTheme = list.matches ? \"dark\" : \"light\";\n applyResolved(element, next, attribute, themeColorRef.current);\n setResolvedTheme(next);\n };\n list.addEventListener(\"change\", handler);\n return () => list.removeEventListener(\"change\", handler);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [theme, attributeKey]);\n\n const setTheme = useCallback(\n (next: ThemeMode) => {\n setThemeState(next);\n if (storageKey && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(storageKey, next);\n } catch {\n /* empty */\n }\n }\n },\n [storageKey],\n );\n\n const toggle = useCallback(() => {\n setTheme(resolvedTheme === \"dark\" ? \"light\" : \"dark\");\n }, [resolvedTheme, setTheme]);\n\n const value = useMemo<ThemeContextValue>(\n () => ({ theme, resolvedTheme, setTheme, toggle }),\n [theme, resolvedTheme, setTheme, toggle],\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\n/**\n * Read and mutate the current theme. Must be used inside a {@link ThemeProvider}.\n */\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error(\"useTheme must be used inside a <ThemeProvider>\");\n return ctx;\n}\n"],"mappings":";;;;AAgBA,IAAM,IAAe,EAAwC,IAAI;AAgCjE,SAAS,EAAQ,GAAgC;CAG7C,OAFI,MAAS,UAAU,MAAS,UAAgB,IAC5C,OAAO,SAAW,MAAoB,UACnC,OAAO,WAAW,8BAA8B,CAAC,CAAC,UAAU,SAAS;AAChF;AAMA,SAAS,EACL,GACA,GACA,GACA,GACI;CACJ,IAAM,IAAQ,MAAM,QAAQ,CAAS,IAAI,IAAY,CAAC,CAAS;CAC/D,KAAK,IAAM,KAAQ,GAAO,EAAQ,aAAa,GAAM,CAAQ;CAC7D,IAAI,KAAc,OAAO,WAAa,KAAa;EAC/C,IAAM,IAAO,SAAS,cAA+B,4BAA0B;EAC/E,AAAI,MAAM,EAAK,UAAU,EAAW;CACxC;AACJ;AAEA,SAAS,EAAW,GAA6C;CAC7D,IAAI,CAAC,KAAc,OAAO,SAAW,KAAa,OAAO;CACzD,IAAI;EACA,IAAM,IAAQ,OAAO,aAAa,QAAQ,CAAU;EAEpD,OADI,MAAU,WAAW,MAAU,UAAU,MAAU,WAAiB,IACjE;CACX,QAAQ;EACJ,OAAO;CACX;AACJ;AAeA,SAAgB,EAAc,EAC1B,aACA,kBAAe,UACf,gBAAa,iBACb,WACA,eAAY,sBACZ,iBACmB;CACnB,IAAM,CAAC,GAAO,KAAiB,QACrB,EAAW,CAAU,KAAK,CACpC,GACM,CAAC,GAAe,KAAoB,QAA8B,EAAQ,CAAK,CAAC,GAEhF,IAAY,EAAa,CAAM,GAE/B,IAAe,MAAM,QAAQ,CAAS,IAAI,EAAU,KAAK,GAAG,IAAI,GAChE,IAAgB,EAAa,CAAU;CAY7C,AAVA,QAAgB;EACZ,IAAM,IAAU,EAAU,UAAU,KAAK,SAAS;EAClD,IAAI,CAAC,GAAS;EACd,IAAM,IAAO,EAAQ,CAAK;EAE1B,AADA,EAAc,GAAS,GAAM,GAAW,EAAc,OAAO,GAC7D,EAAiB,CAAI;CAGzB,GAAG,CAAC,GAAO,CAAY,CAAC,GAExB,QAAgB;EACZ,IAAI,MAAU,YAAY,OAAO,SAAW,KAAa;EACzD,IAAM,IAAO,OAAO,WAAW,8BAA8B,GACvD,UAAsB;GACxB,IAAM,IAAU,EAAU,UAAU,KAAK,SAAS;GAClD,IAAI,CAAC,GAAS;GACd,IAAM,IAAsB,EAAK,UAAU,SAAS;GAEpD,AADA,EAAc,GAAS,GAAM,GAAW,EAAc,OAAO,GAC7D,EAAiB,CAAI;EACzB;EAEA,OADA,EAAK,iBAAiB,UAAU,CAAO,SAC1B,EAAK,oBAAoB,UAAU,CAAO;CAE3D,GAAG,CAAC,GAAO,CAAY,CAAC;CAExB,IAAM,IAAW,GACZ,MAAoB;EAEjB,IADA,EAAc,CAAI,GACd,KAAc,OAAO,SAAW,KAChC,IAAI;GACA,OAAO,aAAa,QAAQ,GAAY,CAAI;EAChD,QAAQ,CAER;CAER,GACA,CAAC,CAAU,CACf,GAEM,IAAS,QAAkB;EAC7B,EAAS,MAAkB,SAAS,UAAU,MAAM;CACxD,GAAG,CAAC,GAAe,CAAQ,CAAC,GAEtB,IAAQ,SACH;EAAE;EAAO;EAAe;EAAU;CAAO,IAChD;EAAC;EAAO;EAAe;EAAU;CAAM,CAC3C;CAEA,OAAO,kBAAC,EAAa,UAAd;EAA8B;EAAQ;CAAgC,CAAA;AACjF;AAKA,SAAgB,IAA8B;CAC1C,IAAM,IAAM,EAAW,CAAY;CACnC,IAAI,CAAC,GAAK,MAAU,MAAM,gDAAgD;CAC1E,OAAO;AACX"}
@@ -0,0 +1,2 @@
1
+ function e(e,t={}){let n=``,r=32768;for(let t=0;t<e.length;t+=r)n+=String.fromCharCode(...e.subarray(t,t+r));let i=btoa(n);return t.urlSafe?i.replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``):i}function t(e){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);for(let e=0;e<r.length;e+=1)i[e]=r.charCodeAt(e);return i}exports.base64ToBytes=t,exports.bytesToBase64=e;
2
+ //# sourceMappingURL=base64.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64.cjs","names":[],"sources":["../../src/utils/base64.ts"],"sourcesContent":["/**\n * Base64-encode bytes, without splatting the whole array into `fromCharCode`.\n *\n * `String.fromCharCode(...bytes)` overflows the argument limit somewhere around\n * a hundred thousand entries — which a compressed save reaches easily — so the\n * conversion walks the buffer in 32 KiB windows. That is also why this is the\n * version worth sharing: the byte-at-a-time loop the other two call sites used\n * has no argument limit either, but it is markedly slower on the payload sizes\n * `compressedStorage` exists for.\n *\n * @param bytes - The bytes to encode.\n * @param options - Pass `urlSafe` for the base64url alphabet (`-`/`_`, unpadded),\n * which is what WebAuthn and anything travelling in a URL needs.\n * @returns Base64 text.\n */\nexport function bytesToBase64(bytes: Uint8Array, options: { urlSafe?: boolean } = {}): string {\n let binary = \"\";\n const chunkSize = 0x8000;\n for (let index = 0; index < bytes.length; index += chunkSize) {\n binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize));\n }\n const encoded = btoa(binary);\n if (!options.urlSafe) return encoded;\n return encoded.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/**\n * Decode base64 into bytes, accepting either alphabet.\n *\n * Takes no `urlSafe` option on purpose: translating `-`/`_` and restoring the\n * padding are no-ops on standard padded base64, so one permissive decoder is\n * correct for both inputs. Getting this half wrong — usually by feeding\n * unpadded base64url straight to `atob` and losing the last byte — is the\n * classic broken-WebAuthn bug.\n *\n * @param value - Base64 or base64url text, with or without `=` padding.\n * @returns The decoded bytes.\n */\nexport function base64ToBytes(value: string): Uint8Array<ArrayBuffer> {\n const standard = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = standard.padEnd(standard.length + ((4 - (standard.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"],"mappings":"AAeA,SAAgB,EAAc,EAAmB,EAAiC,CAAC,EAAW,CAC1F,IAAI,EAAS,GACP,EAAY,MAClB,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAM,OAAQ,GAAS,EAC/C,GAAU,OAAO,aAAa,GAAG,EAAM,SAAS,EAAO,EAAQ,CAAS,CAAC,EAE7E,IAAM,EAAU,KAAK,CAAM,EAE3B,OADK,EAAQ,QACN,EAAQ,QAAQ,MAAO,GAAG,CAAC,CAAC,QAAQ,MAAO,GAAG,CAAC,CAAC,QAAQ,MAAO,EAAE,EAD3C,CAEjC,CAcA,SAAgB,EAAc,EAAwC,CAClE,IAAM,EAAW,EAAM,QAAQ,KAAM,GAAG,CAAC,CAAC,QAAQ,KAAM,GAAG,EACrD,EAAS,EAAS,OAAO,EAAS,QAAW,EAAK,EAAS,OAAS,GAAM,EAAI,GAAG,EACjF,EAAS,KAAK,CAAM,EACpB,EAAQ,IAAI,WAAW,EAAO,MAAM,EAC1C,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAO,OAAQ,GAAS,EAChD,EAAM,GAAS,EAAO,WAAW,CAAK,EAE1C,OAAO,CACX"}
@@ -0,0 +1,16 @@
1
+ //#region src/utils/base64.ts
2
+ function e(e, t = {}) {
3
+ let n = "", r = 32768;
4
+ for (let t = 0; t < e.length; t += r) n += String.fromCharCode(...e.subarray(t, t + r));
5
+ let i = btoa(n);
6
+ return t.urlSafe ? i.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "") : i;
7
+ }
8
+ function t(e) {
9
+ 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);
10
+ for (let e = 0; e < r.length; e += 1) i[e] = r.charCodeAt(e);
11
+ return i;
12
+ }
13
+ //#endregion
14
+ export { t as base64ToBytes, e as bytesToBase64 };
15
+
16
+ //# sourceMappingURL=base64.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64.js","names":[],"sources":["../../src/utils/base64.ts"],"sourcesContent":["/**\n * Base64-encode bytes, without splatting the whole array into `fromCharCode`.\n *\n * `String.fromCharCode(...bytes)` overflows the argument limit somewhere around\n * a hundred thousand entries — which a compressed save reaches easily — so the\n * conversion walks the buffer in 32 KiB windows. That is also why this is the\n * version worth sharing: the byte-at-a-time loop the other two call sites used\n * has no argument limit either, but it is markedly slower on the payload sizes\n * `compressedStorage` exists for.\n *\n * @param bytes - The bytes to encode.\n * @param options - Pass `urlSafe` for the base64url alphabet (`-`/`_`, unpadded),\n * which is what WebAuthn and anything travelling in a URL needs.\n * @returns Base64 text.\n */\nexport function bytesToBase64(bytes: Uint8Array, options: { urlSafe?: boolean } = {}): string {\n let binary = \"\";\n const chunkSize = 0x8000;\n for (let index = 0; index < bytes.length; index += chunkSize) {\n binary += String.fromCharCode(...bytes.subarray(index, index + chunkSize));\n }\n const encoded = btoa(binary);\n if (!options.urlSafe) return encoded;\n return encoded.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/**\n * Decode base64 into bytes, accepting either alphabet.\n *\n * Takes no `urlSafe` option on purpose: translating `-`/`_` and restoring the\n * padding are no-ops on standard padded base64, so one permissive decoder is\n * correct for both inputs. Getting this half wrong — usually by feeding\n * unpadded base64url straight to `atob` and losing the last byte — is the\n * classic broken-WebAuthn bug.\n *\n * @param value - Base64 or base64url text, with or without `=` padding.\n * @returns The decoded bytes.\n */\nexport function base64ToBytes(value: string): Uint8Array<ArrayBuffer> {\n const standard = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = standard.padEnd(standard.length + ((4 - (standard.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"],"mappings":";AAeA,SAAgB,EAAc,GAAmB,IAAiC,CAAC,GAAW;CAC1F,IAAI,IAAS,IACP,IAAY;CAClB,KAAK,IAAI,IAAQ,GAAG,IAAQ,EAAM,QAAQ,KAAS,GAC/C,KAAU,OAAO,aAAa,GAAG,EAAM,SAAS,GAAO,IAAQ,CAAS,CAAC;CAE7E,IAAM,IAAU,KAAK,CAAM;CAE3B,OADK,EAAQ,UACN,EAAQ,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,OAAO,EAAE,IAD3C;AAEjC;AAcA,SAAgB,EAAc,GAAwC;CAClE,IAAM,IAAW,EAAM,QAAQ,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,GAAG,GACrD,IAAS,EAAS,OAAO,EAAS,UAAW,IAAK,EAAS,SAAS,KAAM,GAAI,GAAG,GACjF,IAAS,KAAK,CAAM,GACpB,IAAQ,IAAI,WAAW,EAAO,MAAM;CAC1C,KAAK,IAAI,IAAQ,GAAG,IAAQ,EAAO,QAAQ,KAAS,GAChD,EAAM,KAAS,EAAO,WAAW,CAAK;CAE1C,OAAO;AACX"}
@@ -1,2 +1,2 @@
1
- function e(e,t){return e==null&&t==null?0:e==null?-1:t==null?1:typeof e==`number`&&typeof t==`number`?e-t:e instanceof Date&&t instanceof Date?e.getTime()-t.getTime():typeof e==`boolean`&&typeof t==`boolean`?Number(e)-Number(t):String(e).localeCompare(String(t),void 0,{numeric:!0})}exports.compareValues=e;
1
+ var e=new Intl.Collator(void 0,{numeric:!0});function t(t,n){return t==null&&n==null?0:t==null?-1:n==null?1:typeof t==`number`&&typeof n==`number`?t-n:t instanceof Date&&n instanceof Date?t.getTime()-n.getTime():typeof t==`boolean`&&typeof n==`boolean`?Number(t)-Number(n):e.compare(String(t),String(n))}exports.compareValues=t;
2
2
  //# sourceMappingURL=compare-values.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"compare-values.cjs","names":[],"sources":["../../src/utils/compare-values.ts"],"sourcesContent":["/**\n * Compare two arbitrary cell values with stable, type-aware ordering.\n *\n * The comparator every table in the SDK sorts with, so `DataTable` and\n * `VirtualTable` agree on what \"sorted\" means. The type-aware branches exist\n * because the naive `String(a) < String(b)` gets the two most common cases wrong:\n * numbers would sort `10` before `9`, and dates would sort by their formatted\n * text. Strings fall back to `localeCompare` with `numeric: true`, so `\"item 2\"`\n * lands before `\"item 10\"`.\n *\n * `null` and `undefined` sort first, together — a missing value is not smaller\n * than another missing value.\n *\n * @param a - First value.\n * @param b - Second value.\n * @returns Negative when `a < b`, positive when `a > b`, zero when equal.\n */\nexport function compareValues(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"boolean\" && typeof b === \"boolean\") return Number(a) - Number(b);\n return String(a).localeCompare(String(b), undefined, { numeric: true });\n}\n"],"mappings":"AAiBA,SAAgB,EAAc,EAAY,EAAoB,CAO1D,OANI,GAAK,MAAQ,GAAK,KAAa,EAC/B,GAAK,KAAa,GAClB,GAAK,KAAa,EAClB,OAAO,GAAM,UAAY,OAAO,GAAM,SAAiB,EAAI,EAC3D,aAAa,MAAQ,aAAa,KAAa,EAAE,QAAQ,EAAI,EAAE,QAAQ,EACvE,OAAO,GAAM,WAAa,OAAO,GAAM,UAAkB,OAAO,CAAC,EAAI,OAAO,CAAC,EAC1E,OAAO,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,EAAG,IAAA,GAAW,CAAE,QAAS,EAAK,CAAC,CAC1E"}
1
+ {"version":3,"file":"compare-values.cjs","names":[],"sources":["../../src/utils/compare-values.ts"],"sourcesContent":["/**\n * One collator for every string comparison a table sort makes.\n *\n * `localeCompare(other, undefined, { numeric: true })` builds a collator per\n * call — passing an options bag opts out of the engine's cached-default fast\n * path — and a sort makes O(n log n) of these. Measured at 200k comparisons:\n * 453 ms through `localeCompare` against 25 ms through a hoisted collator.\n */\nconst TEXT_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/**\n * Compare two arbitrary cell values with stable, type-aware ordering.\n *\n * The comparator every table in the SDK sorts with, so `DataTable` and\n * `VirtualTable` agree on what \"sorted\" means. The type-aware branches exist\n * because the naive `String(a) < String(b)` gets the two most common cases wrong:\n * numbers would sort `10` before `9`, and dates would sort by their formatted\n * text. Strings fall back to `localeCompare` with `numeric: true`, so `\"item 2\"`\n * lands before `\"item 10\"`.\n *\n * `null` and `undefined` sort first, together — a missing value is not smaller\n * than another missing value.\n *\n * @param a - First value.\n * @param b - Second value.\n * @returns Negative when `a < b`, positive when `a > b`, zero when equal.\n */\nexport function compareValues(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"boolean\" && typeof b === \"boolean\") return Number(a) - Number(b);\n return TEXT_COLLATOR.compare(String(a), String(b));\n}\n"],"mappings":"AAQA,IAAM,EAAgB,IAAI,KAAK,SAAS,IAAA,GAAW,CAAE,QAAS,EAAK,CAAC,EAmBpE,SAAgB,EAAc,EAAY,EAAoB,CAO1D,OANI,GAAK,MAAQ,GAAK,KAAa,EAC/B,GAAK,KAAa,GAClB,GAAK,KAAa,EAClB,OAAO,GAAM,UAAY,OAAO,GAAM,SAAiB,EAAI,EAC3D,aAAa,MAAQ,aAAa,KAAa,EAAE,QAAQ,EAAI,EAAE,QAAQ,EACvE,OAAO,GAAM,WAAa,OAAO,GAAM,UAAkB,OAAO,CAAC,EAAI,OAAO,CAAC,EAC1E,EAAc,QAAQ,OAAO,CAAC,EAAG,OAAO,CAAC,CAAC,CACrD"}
@@ -1,8 +1,9 @@
1
1
  //#region src/utils/compare-values.ts
2
- function e(e, t) {
3
- return e == null && t == null ? 0 : e == null ? -1 : t == null ? 1 : typeof e == "number" && typeof t == "number" ? e - t : e instanceof Date && t instanceof Date ? e.getTime() - t.getTime() : typeof e == "boolean" && typeof t == "boolean" ? Number(e) - Number(t) : String(e).localeCompare(String(t), void 0, { numeric: !0 });
2
+ var e = new Intl.Collator(void 0, { numeric: !0 });
3
+ function t(t, n) {
4
+ return t == null && n == null ? 0 : t == null ? -1 : n == null ? 1 : typeof t == "number" && typeof n == "number" ? t - n : t instanceof Date && n instanceof Date ? t.getTime() - n.getTime() : typeof t == "boolean" && typeof n == "boolean" ? Number(t) - Number(n) : e.compare(String(t), String(n));
4
5
  }
5
6
  //#endregion
6
- export { e as compareValues };
7
+ export { t as compareValues };
7
8
 
8
9
  //# sourceMappingURL=compare-values.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compare-values.js","names":[],"sources":["../../src/utils/compare-values.ts"],"sourcesContent":["/**\n * Compare two arbitrary cell values with stable, type-aware ordering.\n *\n * The comparator every table in the SDK sorts with, so `DataTable` and\n * `VirtualTable` agree on what \"sorted\" means. The type-aware branches exist\n * because the naive `String(a) < String(b)` gets the two most common cases wrong:\n * numbers would sort `10` before `9`, and dates would sort by their formatted\n * text. Strings fall back to `localeCompare` with `numeric: true`, so `\"item 2\"`\n * lands before `\"item 10\"`.\n *\n * `null` and `undefined` sort first, together — a missing value is not smaller\n * than another missing value.\n *\n * @param a - First value.\n * @param b - Second value.\n * @returns Negative when `a < b`, positive when `a > b`, zero when equal.\n */\nexport function compareValues(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"boolean\" && typeof b === \"boolean\") return Number(a) - Number(b);\n return String(a).localeCompare(String(b), undefined, { numeric: true });\n}\n"],"mappings":";AAiBA,SAAgB,EAAc,GAAY,GAAoB;CAO1D,OANI,KAAK,QAAQ,KAAK,OAAa,IAC/B,KAAK,OAAa,KAClB,KAAK,OAAa,IAClB,OAAO,KAAM,YAAY,OAAO,KAAM,WAAiB,IAAI,IAC3D,aAAa,QAAQ,aAAa,OAAa,EAAE,QAAQ,IAAI,EAAE,QAAQ,IACvE,OAAO,KAAM,aAAa,OAAO,KAAM,YAAkB,OAAO,CAAC,IAAI,OAAO,CAAC,IAC1E,OAAO,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,GAAG,KAAA,GAAW,EAAE,SAAS,GAAK,CAAC;AAC1E"}
1
+ {"version":3,"file":"compare-values.js","names":[],"sources":["../../src/utils/compare-values.ts"],"sourcesContent":["/**\n * One collator for every string comparison a table sort makes.\n *\n * `localeCompare(other, undefined, { numeric: true })` builds a collator per\n * call — passing an options bag opts out of the engine's cached-default fast\n * path — and a sort makes O(n log n) of these. Measured at 200k comparisons:\n * 453 ms through `localeCompare` against 25 ms through a hoisted collator.\n */\nconst TEXT_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/**\n * Compare two arbitrary cell values with stable, type-aware ordering.\n *\n * The comparator every table in the SDK sorts with, so `DataTable` and\n * `VirtualTable` agree on what \"sorted\" means. The type-aware branches exist\n * because the naive `String(a) < String(b)` gets the two most common cases wrong:\n * numbers would sort `10` before `9`, and dates would sort by their formatted\n * text. Strings fall back to `localeCompare` with `numeric: true`, so `\"item 2\"`\n * lands before `\"item 10\"`.\n *\n * `null` and `undefined` sort first, together — a missing value is not smaller\n * than another missing value.\n *\n * @param a - First value.\n * @param b - Second value.\n * @returns Negative when `a < b`, positive when `a > b`, zero when equal.\n */\nexport function compareValues(a: unknown, b: unknown): number {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();\n if (typeof a === \"boolean\" && typeof b === \"boolean\") return Number(a) - Number(b);\n return TEXT_COLLATOR.compare(String(a), String(b));\n}\n"],"mappings":";AAQA,IAAM,IAAgB,IAAI,KAAK,SAAS,KAAA,GAAW,EAAE,SAAS,GAAK,CAAC;AAmBpE,SAAgB,EAAc,GAAY,GAAoB;CAO1D,OANI,KAAK,QAAQ,KAAK,OAAa,IAC/B,KAAK,OAAa,KAClB,KAAK,OAAa,IAClB,OAAO,KAAM,YAAY,OAAO,KAAM,WAAiB,IAAI,IAC3D,aAAa,QAAQ,aAAa,OAAa,EAAE,QAAQ,IAAI,EAAE,QAAQ,IACvE,OAAO,KAAM,aAAa,OAAO,KAAM,YAAkB,OAAO,CAAC,IAAI,OAAO,CAAC,IAC1E,EAAc,QAAQ,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AACrD"}
@@ -1,2 +1,2 @@
1
- let e=require("fflate");var t=`~tgz1:`;function n(e){let t=``,n=32768;for(let r=0;r<e.length;r+=n)t+=String.fromCharCode(...e.subarray(r,r+n));return btoa(t)}function r(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.charCodeAt(e);return n}function i(r){let i=JSON.stringify(r);return`${t}${n((0,e.gzipSync)(new TextEncoder().encode(i)))}`}function a(n){if(!n.startsWith(t))return JSON.parse(n);let i=(0,e.gunzipSync)(r(n.slice(6)));return JSON.parse(new TextDecoder().decode(i))}var o={serialize:i,deserialize:a},s={get(e,t){if(typeof window>`u`)return t;try{let n=window.localStorage.getItem(e);return n===null?t:a(n)}catch{return t}},set(e,t){if(typeof window>`u`)return;let n;try{n=i(t)}catch{n=JSON.stringify(t)}try{window.localStorage.setItem(e,n)}catch{}}};exports.compressToString=i,exports.compressedStorage=s,exports.compressedStorageCodec=o,exports.decompressFromString=a;
1
+ const e=require("./storage.cjs"),t=require("./base64.cjs");let n=require("fflate");var r=`~tgz1:`;function i(e){let i=JSON.stringify(e),a=(0,n.gzipSync)(new TextEncoder().encode(i));return`${r}${t.bytesToBase64(a)}`}function a(e){if(!e.startsWith(r))return JSON.parse(e);let i=(0,n.gunzipSync)(t.base64ToBytes(e.slice(6)));return JSON.parse(new TextDecoder().decode(i))}var o={serialize:i,deserialize:a},s=e.createJsonStorage(o);exports.compressToString=i,exports.compressedStorage=s,exports.compressedStorageCodec=o,exports.decompressFromString=a;
2
2
  //# sourceMappingURL=compressed-storage.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"compressed-storage.cjs","names":[],"sources":["../../src/utils/compressed-storage.ts"],"sourcesContent":["import { gunzipSync, gzipSync } from \"fflate\";\n\n/**\n * Gzip-backed `localStorage`, for payloads that would otherwise eat the quota.\n *\n * Kept in its own module rather than folded into {@link storage} so that\n * importing the plain typed wrapper never drags `fflate` into the bundle.\n *\n * @tempest-limits empty-catch — every operation here is best-effort by\n * contract, exactly like {@link storage}. `localStorage` throws on quota\n * exhaustion, in Safari private mode, and when a cross-origin frame has storage\n * blocked; a caller persisting state has no recovery to run and no message to\n * show, so the write is dropped and the value stays in memory for the session.\n */\n\n/**\n * Prefix stamped on every value this module writes.\n *\n * It makes the format self-describing, which is what lets a read fall back to\n * plain JSON: a key that predates compression — or that a degraded write stored\n * uncompressed — is still readable, so turning compression on for an existing\n * key does not orphan the data already there. The character also cannot open a\n * JSON document, so the two cases can never be confused.\n */\nconst MARKER = \"~tgz1:\";\n\n/**\n * Base64-encode bytes without splatting the whole array into `fromCharCode`.\n *\n * `String.fromCharCode(...bytes)` overflows the argument limit somewhere around\n * a hundred thousand entries, which a compressed save reaches easily, so the\n * conversion walks the buffer in 32 KiB windows instead.\n */\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n const chunkSize = 0x8000;\n for (let i = 0; i < bytes.length; i += chunkSize) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\n }\n return btoa(binary);\n}\n\n/** Inverse of {@link bytesToBase64}. */\nfunction base64ToBytes(base64: string): Uint8Array {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/**\n * Serialize a value to a gzipped, base64 string carrying the format marker.\n *\n * Base64 costs a third more characters than the raw compressed bytes, and\n * `localStorage` bills two bytes per character on top of that. Packing the\n * bytes into UTF-16 code units directly would be denser, but lone surrogates\n * survive neither every storage implementation nor a JSON round-trip, and a\n * save that decodes to garbage is far worse than one that is bigger. Even with\n * that overhead a typical JSON document lands well under a third of its\n * uncompressed size.\n *\n * @typeParam T - The value being stored.\n * @param value - Any JSON-serializable value.\n * @returns The encoded string, ready for `localStorage`.\n */\nexport function compressToString<T>(value: T): string {\n const json = JSON.stringify(value);\n const bytes = gzipSync(new TextEncoder().encode(json));\n return `${MARKER}${bytesToBase64(bytes)}`;\n}\n\n/**\n * Decode a string produced by {@link compressToString}.\n *\n * A string without the marker is parsed as plain JSON, so values written before\n * compression was enabled — or by a write that fell back after `gzipSync`\n * failed — still read back.\n *\n * @typeParam T - The expected value shape.\n * @param raw - The stored string.\n * @returns The decoded value.\n * @throws If the payload is neither valid compressed data nor valid JSON.\n */\nexport function decompressFromString<T>(raw: string): T {\n if (!raw.startsWith(MARKER)) return JSON.parse(raw) as T;\n const bytes = gunzipSync(base64ToBytes(raw.slice(MARKER.length)));\n return JSON.parse(new TextDecoder().decode(bytes)) as T;\n}\n\n/**\n * Codec pair for {@link useLocalStorage}, so a compressed key gets the hook's\n * cross-tab sync and SSR guard for free.\n *\n * @example\n * const [save, setSave] = useLocalStorage(\"save\", EMPTY_SAVE, compressedStorageCodec);\n */\nexport const compressedStorageCodec = {\n serialize: compressToString,\n deserialize: decompressFromString,\n};\n\n/**\n * Typed `localStorage` wrapper that gzips what it writes.\n *\n * Mirrors {@link storage} so the two are interchangeable at the call site; the\n * difference is only in how the value is encoded.\n */\nexport const compressedStorage = {\n /**\n * Read and decompress a key.\n *\n * @typeParam T - The expected value shape.\n * @param key - Storage key.\n * @param fallback - Returned when the key is absent, unreadable, or corrupt.\n * @returns The stored value, or `fallback`.\n */\n get<T>(key: string, fallback: T): T {\n if (typeof window === \"undefined\") return fallback;\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? fallback : decompressFromString<T>(raw);\n } catch {\n return fallback;\n }\n },\n\n /**\n * Compress and write a key.\n *\n * When compression itself fails the value is written as plain JSON rather\n * than dropped: a slightly larger record still loads, an absent one does\n * not. Only a storage-level failure — quota, blocked storage — loses the\n * write.\n *\n * @typeParam T - The value being stored.\n * @param key - Storage key.\n * @param value - Any JSON-serializable value.\n */\n set<T>(key: string, value: T): void {\n if (typeof window === \"undefined\") return;\n let encoded: string;\n try {\n encoded = compressToString(value);\n } catch {\n encoded = JSON.stringify(value);\n }\n try {\n window.localStorage.setItem(key, encoded);\n } catch {\n /* empty */\n }\n },\n};\n"],"mappings":"wBAwBA,IAAM,EAAS,SASf,SAAS,EAAc,EAA2B,CAC9C,IAAI,EAAS,GACP,EAAY,MAClB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,GAAK,EACnC,GAAU,OAAO,aAAa,GAAG,EAAM,SAAS,EAAG,EAAI,CAAS,CAAC,EAErE,OAAO,KAAK,CAAM,CACtB,CAGA,SAAS,EAAc,EAA4B,CAC/C,IAAM,EAAS,KAAK,CAAM,EACpB,EAAQ,IAAI,WAAW,EAAO,MAAM,EAC1C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,GAAK,EACpC,EAAM,GAAK,EAAO,WAAW,CAAC,EAElC,OAAO,CACX,CAiBA,SAAgB,EAAoB,EAAkB,CAClD,IAAM,EAAO,KAAK,UAAU,CAAK,EAEjC,MAAO,GAAG,IAAS,GADb,EAAQ,EAAA,SAAA,CAAS,IAAI,YAAY,CAAC,CAAC,OAAO,CAAI,CACnB,CAAK,GAC1C,CAcA,SAAgB,EAAwB,EAAgB,CACpD,GAAI,CAAC,EAAI,WAAW,CAAM,EAAG,OAAO,KAAK,MAAM,CAAG,EAClD,IAAM,GAAA,EAAQ,EAAA,WAAA,CAAW,EAAc,EAAI,MAAM,CAAa,CAAC,CAAC,EAChE,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,CAAK,CAAC,CACrD,CASA,IAAa,EAAyB,CAClC,UAAW,EACX,YAAa,CACjB,EAQa,EAAoB,CAS7B,IAAO,EAAa,EAAgB,CAChC,GAAI,OAAO,OAAW,IAAa,OAAO,EAC1C,GAAI,CACA,IAAM,EAAM,OAAO,aAAa,QAAQ,CAAG,EAC3C,OAAO,IAAQ,KAAO,EAAW,EAAwB,CAAG,CAChE,MAAQ,CACJ,OAAO,CACX,CACJ,EAcA,IAAO,EAAa,EAAgB,CAChC,GAAI,OAAO,OAAW,IAAa,OACnC,IAAI,EACJ,GAAI,CACA,EAAU,EAAiB,CAAK,CACpC,MAAQ,CACJ,EAAU,KAAK,UAAU,CAAK,CAClC,CACA,GAAI,CACA,OAAO,aAAa,QAAQ,EAAK,CAAO,CAC5C,MAAQ,CAER,CACJ,CACJ"}
1
+ {"version":3,"file":"compressed-storage.cjs","names":[],"sources":["../../src/utils/compressed-storage.ts"],"sourcesContent":["import { gunzipSync, gzipSync } from \"fflate\";\n\nimport { base64ToBytes, bytesToBase64 } from \"./base64\";\n\nimport { createJsonStorage, type JsonStorage, type StorageCodec } from \"./storage\";\n\n/**\n * Gzip-backed `localStorage`, for payloads that would otherwise eat the quota.\n *\n * Kept in its own module rather than folded into {@link storage} so that\n * importing the plain typed wrapper never drags `fflate` into the bundle.\n *\n * @tempest-limits empty-catch — every operation here is best-effort by\n * contract, exactly like {@link storage}. `localStorage` throws on quota\n * exhaustion, in Safari private mode, and when a cross-origin frame has storage\n * blocked; a caller persisting state has no recovery to run and no message to\n * show, so the write is dropped and the value stays in memory for the session.\n */\n\n/**\n * Prefix stamped on every value this module writes.\n *\n * It makes the format self-describing, which is what lets a read fall back to\n * plain JSON: a key that predates compression — or that a degraded write stored\n * uncompressed — is still readable, so turning compression on for an existing\n * key does not orphan the data already there. The character also cannot open a\n * JSON document, so the two cases can never be confused.\n */\nconst MARKER = \"~tgz1:\";\n\n/**\n * Serialize a value to a gzipped, base64 string carrying the format marker.\n *\n * Base64 costs a third more characters than the raw compressed bytes, and\n * `localStorage` bills two bytes per character on top of that. Packing the\n * bytes into UTF-16 code units directly would be denser, but lone surrogates\n * survive neither every storage implementation nor a JSON round-trip, and a\n * save that decodes to garbage is far worse than one that is bigger. Even with\n * that overhead a typical JSON document lands well under a third of its\n * uncompressed size.\n *\n * @typeParam T - The value being stored.\n * @param value - Any JSON-serializable value.\n * @returns The encoded string, ready for `localStorage`.\n */\nexport function compressToString<T>(value: T): string {\n const json = JSON.stringify(value);\n const bytes = gzipSync(new TextEncoder().encode(json));\n return `${MARKER}${bytesToBase64(bytes)}`;\n}\n\n/**\n * Decode a string produced by {@link compressToString}.\n *\n * A string without the marker is parsed as plain JSON, so values written before\n * compression was enabled — or by a write that fell back after `gzipSync`\n * failed — still read back.\n *\n * @typeParam T - The expected value shape.\n * @param raw - The stored string.\n * @returns The decoded value.\n * @throws If the payload is neither valid compressed data nor valid JSON.\n */\nexport function decompressFromString<T>(raw: string): T {\n if (!raw.startsWith(MARKER)) return JSON.parse(raw) as T;\n const bytes = gunzipSync(base64ToBytes(raw.slice(MARKER.length)));\n return JSON.parse(new TextDecoder().decode(bytes)) as T;\n}\n\n/**\n * Codec pair for {@link useLocalStorage}, so a compressed key gets the hook's\n * cross-tab sync and SSR guard for free.\n *\n * @example\n * const [save, setSave] = useLocalStorage(\"save\", EMPTY_SAVE, compressedStorageCodec);\n */\nexport const compressedStorageCodec: StorageCodec = {\n serialize: compressToString,\n deserialize: decompressFromString,\n};\n\n/**\n * Typed `localStorage` wrapper that gzips what it writes.\n *\n * {@link createJsonStorage} with {@link compressedStorageCodec}, so it is the\n * same implementation as {@link storage} and genuinely interchangeable with it —\n * `get`, `set` and `remove`, differing only in how the value is encoded. It used\n * to be a hand-written copy that had no `remove`, which made that promise false\n * for anybody who took the docstring at its word.\n *\n * When compression itself fails the value is written as plain JSON rather than\n * dropped: a slightly larger record still loads, an absent one does not. Only a\n * storage-level failure — quota, blocked storage — loses the write.\n */\nexport const compressedStorage: JsonStorage = createJsonStorage(compressedStorageCodec);\n"],"mappings":"mFA4BA,IAAM,EAAS,SAiBf,SAAgB,EAAoB,EAAkB,CAClD,IAAM,EAAO,KAAK,UAAU,CAAK,EAC3B,GAAA,EAAQ,EAAA,SAAA,CAAS,IAAI,YAAY,CAAC,CAAC,OAAO,CAAI,CAAC,EACrD,MAAO,GAAG,IAAS,EAAA,cAAc,CAAK,GAC1C,CAcA,SAAgB,EAAwB,EAAgB,CACpD,GAAI,CAAC,EAAI,WAAW,CAAM,EAAG,OAAO,KAAK,MAAM,CAAG,EAClD,IAAM,GAAA,EAAQ,EAAA,WAAA,CAAW,EAAA,cAAc,EAAI,MAAM,CAAa,CAAC,CAAC,EAChE,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,CAAK,CAAC,CACrD,CASA,IAAa,EAAuC,CAChD,UAAW,EACX,YAAa,CACjB,EAea,EAAiC,EAAA,kBAAkB,CAAsB"}
@@ -1,52 +1,22 @@
1
- import { gunzipSync as e, gzipSync as t } from "fflate";
1
+ import { createJsonStorage as e } from "./storage.js";
2
+ import { base64ToBytes as t, bytesToBase64 as n } from "./base64.js";
3
+ import { gunzipSync as r, gzipSync as i } from "fflate";
2
4
  //#region src/utils/compressed-storage.ts
3
- var n = "~tgz1:";
4
- function r(e) {
5
- let t = "", n = 32768;
6
- for (let r = 0; r < e.length; r += n) t += String.fromCharCode(...e.subarray(r, r + n));
7
- return btoa(t);
5
+ var a = "~tgz1:";
6
+ function o(e) {
7
+ let t = JSON.stringify(e), r = i(new TextEncoder().encode(t));
8
+ return `${a}${n(r)}`;
8
9
  }
9
- function i(e) {
10
- let t = atob(e), n = new Uint8Array(t.length);
11
- for (let e = 0; e < t.length; e += 1) n[e] = t.charCodeAt(e);
12
- return n;
10
+ function s(e) {
11
+ if (!e.startsWith(a)) return JSON.parse(e);
12
+ let n = r(t(e.slice(6)));
13
+ return JSON.parse(new TextDecoder().decode(n));
13
14
  }
14
- function a(e) {
15
- let i = JSON.stringify(e);
16
- return `${n}${r(t(new TextEncoder().encode(i)))}`;
17
- }
18
- function o(t) {
19
- if (!t.startsWith(n)) return JSON.parse(t);
20
- let r = e(i(t.slice(6)));
21
- return JSON.parse(new TextDecoder().decode(r));
22
- }
23
- var s = {
24
- serialize: a,
25
- deserialize: o
26
- }, c = {
27
- get(e, t) {
28
- if (typeof window > "u") return t;
29
- try {
30
- let n = window.localStorage.getItem(e);
31
- return n === null ? t : o(n);
32
- } catch {
33
- return t;
34
- }
35
- },
36
- set(e, t) {
37
- if (typeof window > "u") return;
38
- let n;
39
- try {
40
- n = a(t);
41
- } catch {
42
- n = JSON.stringify(t);
43
- }
44
- try {
45
- window.localStorage.setItem(e, n);
46
- } catch {}
47
- }
48
- };
15
+ var c = {
16
+ serialize: o,
17
+ deserialize: s
18
+ }, l = e(c);
49
19
  //#endregion
50
- export { a as compressToString, c as compressedStorage, s as compressedStorageCodec, o as decompressFromString };
20
+ export { o as compressToString, l as compressedStorage, c as compressedStorageCodec, s as decompressFromString };
51
21
 
52
22
  //# sourceMappingURL=compressed-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compressed-storage.js","names":[],"sources":["../../src/utils/compressed-storage.ts"],"sourcesContent":["import { gunzipSync, gzipSync } from \"fflate\";\n\n/**\n * Gzip-backed `localStorage`, for payloads that would otherwise eat the quota.\n *\n * Kept in its own module rather than folded into {@link storage} so that\n * importing the plain typed wrapper never drags `fflate` into the bundle.\n *\n * @tempest-limits empty-catch — every operation here is best-effort by\n * contract, exactly like {@link storage}. `localStorage` throws on quota\n * exhaustion, in Safari private mode, and when a cross-origin frame has storage\n * blocked; a caller persisting state has no recovery to run and no message to\n * show, so the write is dropped and the value stays in memory for the session.\n */\n\n/**\n * Prefix stamped on every value this module writes.\n *\n * It makes the format self-describing, which is what lets a read fall back to\n * plain JSON: a key that predates compression — or that a degraded write stored\n * uncompressed — is still readable, so turning compression on for an existing\n * key does not orphan the data already there. The character also cannot open a\n * JSON document, so the two cases can never be confused.\n */\nconst MARKER = \"~tgz1:\";\n\n/**\n * Base64-encode bytes without splatting the whole array into `fromCharCode`.\n *\n * `String.fromCharCode(...bytes)` overflows the argument limit somewhere around\n * a hundred thousand entries, which a compressed save reaches easily, so the\n * conversion walks the buffer in 32 KiB windows instead.\n */\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n const chunkSize = 0x8000;\n for (let i = 0; i < bytes.length; i += chunkSize) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\n }\n return btoa(binary);\n}\n\n/** Inverse of {@link bytesToBase64}. */\nfunction base64ToBytes(base64: string): Uint8Array {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/**\n * Serialize a value to a gzipped, base64 string carrying the format marker.\n *\n * Base64 costs a third more characters than the raw compressed bytes, and\n * `localStorage` bills two bytes per character on top of that. Packing the\n * bytes into UTF-16 code units directly would be denser, but lone surrogates\n * survive neither every storage implementation nor a JSON round-trip, and a\n * save that decodes to garbage is far worse than one that is bigger. Even with\n * that overhead a typical JSON document lands well under a third of its\n * uncompressed size.\n *\n * @typeParam T - The value being stored.\n * @param value - Any JSON-serializable value.\n * @returns The encoded string, ready for `localStorage`.\n */\nexport function compressToString<T>(value: T): string {\n const json = JSON.stringify(value);\n const bytes = gzipSync(new TextEncoder().encode(json));\n return `${MARKER}${bytesToBase64(bytes)}`;\n}\n\n/**\n * Decode a string produced by {@link compressToString}.\n *\n * A string without the marker is parsed as plain JSON, so values written before\n * compression was enabled — or by a write that fell back after `gzipSync`\n * failed — still read back.\n *\n * @typeParam T - The expected value shape.\n * @param raw - The stored string.\n * @returns The decoded value.\n * @throws If the payload is neither valid compressed data nor valid JSON.\n */\nexport function decompressFromString<T>(raw: string): T {\n if (!raw.startsWith(MARKER)) return JSON.parse(raw) as T;\n const bytes = gunzipSync(base64ToBytes(raw.slice(MARKER.length)));\n return JSON.parse(new TextDecoder().decode(bytes)) as T;\n}\n\n/**\n * Codec pair for {@link useLocalStorage}, so a compressed key gets the hook's\n * cross-tab sync and SSR guard for free.\n *\n * @example\n * const [save, setSave] = useLocalStorage(\"save\", EMPTY_SAVE, compressedStorageCodec);\n */\nexport const compressedStorageCodec = {\n serialize: compressToString,\n deserialize: decompressFromString,\n};\n\n/**\n * Typed `localStorage` wrapper that gzips what it writes.\n *\n * Mirrors {@link storage} so the two are interchangeable at the call site; the\n * difference is only in how the value is encoded.\n */\nexport const compressedStorage = {\n /**\n * Read and decompress a key.\n *\n * @typeParam T - The expected value shape.\n * @param key - Storage key.\n * @param fallback - Returned when the key is absent, unreadable, or corrupt.\n * @returns The stored value, or `fallback`.\n */\n get<T>(key: string, fallback: T): T {\n if (typeof window === \"undefined\") return fallback;\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? fallback : decompressFromString<T>(raw);\n } catch {\n return fallback;\n }\n },\n\n /**\n * Compress and write a key.\n *\n * When compression itself fails the value is written as plain JSON rather\n * than dropped: a slightly larger record still loads, an absent one does\n * not. Only a storage-level failure — quota, blocked storage — loses the\n * write.\n *\n * @typeParam T - The value being stored.\n * @param key - Storage key.\n * @param value - Any JSON-serializable value.\n */\n set<T>(key: string, value: T): void {\n if (typeof window === \"undefined\") return;\n let encoded: string;\n try {\n encoded = compressToString(value);\n } catch {\n encoded = JSON.stringify(value);\n }\n try {\n window.localStorage.setItem(key, encoded);\n } catch {\n /* empty */\n }\n },\n};\n"],"mappings":";;AAwBA,IAAM,IAAS;AASf,SAAS,EAAc,GAA2B;CAC9C,IAAI,IAAS,IACP,IAAY;CAClB,KAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK,GACnC,KAAU,OAAO,aAAa,GAAG,EAAM,SAAS,GAAG,IAAI,CAAS,CAAC;CAErE,OAAO,KAAK,CAAM;AACtB;AAGA,SAAS,EAAc,GAA4B;CAC/C,IAAM,IAAS,KAAK,CAAM,GACpB,IAAQ,IAAI,WAAW,EAAO,MAAM;CAC1C,KAAK,IAAI,IAAI,GAAG,IAAI,EAAO,QAAQ,KAAK,GACpC,EAAM,KAAK,EAAO,WAAW,CAAC;CAElC,OAAO;AACX;AAiBA,SAAgB,EAAoB,GAAkB;CAClD,IAAM,IAAO,KAAK,UAAU,CAAK;CAEjC,OAAO,GAAG,IAAS,EADL,EAAS,IAAI,YAAY,CAAC,CAAC,OAAO,CAAI,CACnB,CAAK;AAC1C;AAcA,SAAgB,EAAwB,GAAgB;CACpD,IAAI,CAAC,EAAI,WAAW,CAAM,GAAG,OAAO,KAAK,MAAM,CAAG;CAClD,IAAM,IAAQ,EAAW,EAAc,EAAI,MAAM,CAAa,CAAC,CAAC;CAChE,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,CAAK,CAAC;AACrD;AASA,IAAa,IAAyB;CAClC,WAAW;CACX,aAAa;AACjB,GAQa,IAAoB;CAS7B,IAAO,GAAa,GAAgB;EAChC,IAAI,OAAO,SAAW,KAAa,OAAO;EAC1C,IAAI;GACA,IAAM,IAAM,OAAO,aAAa,QAAQ,CAAG;GAC3C,OAAO,MAAQ,OAAO,IAAW,EAAwB,CAAG;EAChE,QAAQ;GACJ,OAAO;EACX;CACJ;CAcA,IAAO,GAAa,GAAgB;EAChC,IAAI,OAAO,SAAW,KAAa;EACnC,IAAI;EACJ,IAAI;GACA,IAAU,EAAiB,CAAK;EACpC,QAAQ;GACJ,IAAU,KAAK,UAAU,CAAK;EAClC;EACA,IAAI;GACA,OAAO,aAAa,QAAQ,GAAK,CAAO;EAC5C,QAAQ,CAER;CACJ;AACJ"}
1
+ {"version":3,"file":"compressed-storage.js","names":[],"sources":["../../src/utils/compressed-storage.ts"],"sourcesContent":["import { gunzipSync, gzipSync } from \"fflate\";\n\nimport { base64ToBytes, bytesToBase64 } from \"./base64\";\n\nimport { createJsonStorage, type JsonStorage, type StorageCodec } from \"./storage\";\n\n/**\n * Gzip-backed `localStorage`, for payloads that would otherwise eat the quota.\n *\n * Kept in its own module rather than folded into {@link storage} so that\n * importing the plain typed wrapper never drags `fflate` into the bundle.\n *\n * @tempest-limits empty-catch — every operation here is best-effort by\n * contract, exactly like {@link storage}. `localStorage` throws on quota\n * exhaustion, in Safari private mode, and when a cross-origin frame has storage\n * blocked; a caller persisting state has no recovery to run and no message to\n * show, so the write is dropped and the value stays in memory for the session.\n */\n\n/**\n * Prefix stamped on every value this module writes.\n *\n * It makes the format self-describing, which is what lets a read fall back to\n * plain JSON: a key that predates compression — or that a degraded write stored\n * uncompressed — is still readable, so turning compression on for an existing\n * key does not orphan the data already there. The character also cannot open a\n * JSON document, so the two cases can never be confused.\n */\nconst MARKER = \"~tgz1:\";\n\n/**\n * Serialize a value to a gzipped, base64 string carrying the format marker.\n *\n * Base64 costs a third more characters than the raw compressed bytes, and\n * `localStorage` bills two bytes per character on top of that. Packing the\n * bytes into UTF-16 code units directly would be denser, but lone surrogates\n * survive neither every storage implementation nor a JSON round-trip, and a\n * save that decodes to garbage is far worse than one that is bigger. Even with\n * that overhead a typical JSON document lands well under a third of its\n * uncompressed size.\n *\n * @typeParam T - The value being stored.\n * @param value - Any JSON-serializable value.\n * @returns The encoded string, ready for `localStorage`.\n */\nexport function compressToString<T>(value: T): string {\n const json = JSON.stringify(value);\n const bytes = gzipSync(new TextEncoder().encode(json));\n return `${MARKER}${bytesToBase64(bytes)}`;\n}\n\n/**\n * Decode a string produced by {@link compressToString}.\n *\n * A string without the marker is parsed as plain JSON, so values written before\n * compression was enabled — or by a write that fell back after `gzipSync`\n * failed — still read back.\n *\n * @typeParam T - The expected value shape.\n * @param raw - The stored string.\n * @returns The decoded value.\n * @throws If the payload is neither valid compressed data nor valid JSON.\n */\nexport function decompressFromString<T>(raw: string): T {\n if (!raw.startsWith(MARKER)) return JSON.parse(raw) as T;\n const bytes = gunzipSync(base64ToBytes(raw.slice(MARKER.length)));\n return JSON.parse(new TextDecoder().decode(bytes)) as T;\n}\n\n/**\n * Codec pair for {@link useLocalStorage}, so a compressed key gets the hook's\n * cross-tab sync and SSR guard for free.\n *\n * @example\n * const [save, setSave] = useLocalStorage(\"save\", EMPTY_SAVE, compressedStorageCodec);\n */\nexport const compressedStorageCodec: StorageCodec = {\n serialize: compressToString,\n deserialize: decompressFromString,\n};\n\n/**\n * Typed `localStorage` wrapper that gzips what it writes.\n *\n * {@link createJsonStorage} with {@link compressedStorageCodec}, so it is the\n * same implementation as {@link storage} and genuinely interchangeable with it —\n * `get`, `set` and `remove`, differing only in how the value is encoded. It used\n * to be a hand-written copy that had no `remove`, which made that promise false\n * for anybody who took the docstring at its word.\n *\n * When compression itself fails the value is written as plain JSON rather than\n * dropped: a slightly larger record still loads, an absent one does not. Only a\n * storage-level failure — quota, blocked storage — loses the write.\n */\nexport const compressedStorage: JsonStorage = createJsonStorage(compressedStorageCodec);\n"],"mappings":";;;;AA4BA,IAAM,IAAS;AAiBf,SAAgB,EAAoB,GAAkB;CAClD,IAAM,IAAO,KAAK,UAAU,CAAK,GAC3B,IAAQ,EAAS,IAAI,YAAY,CAAC,CAAC,OAAO,CAAI,CAAC;CACrD,OAAO,GAAG,IAAS,EAAc,CAAK;AAC1C;AAcA,SAAgB,EAAwB,GAAgB;CACpD,IAAI,CAAC,EAAI,WAAW,CAAM,GAAG,OAAO,KAAK,MAAM,CAAG;CAClD,IAAM,IAAQ,EAAW,EAAc,EAAI,MAAM,CAAa,CAAC,CAAC;CAChE,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,OAAO,CAAK,CAAC;AACrD;AASA,IAAa,IAAuC;CAChD,WAAW;CACX,aAAa;AACjB,GAea,IAAiC,EAAkB,CAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev-mode.cjs","names":[],"sources":["../../src/utils/dev-mode.ts"],"sourcesContent":["/**\n * Whether the consuming app was built for development.\n *\n * Reads `process.env.NODE_ENV`, which every supported bundler (Vite, webpack,\n * Rspack, Parcel) replaces with a literal **while building the app**. That\n * timing is the whole point: `import.meta.env.DEV` looks equivalent and is not,\n * because Vite replaces it while building *this package*, so a published\n * artifact carries the constant `false` and every guard behind it becomes dead\n * code the app's own dev server can no longer switch on.\n *\n * The expression is written out in full, and the failure is caught rather than\n * guarded against. A `typeof process === \"undefined\"` check would read as the\n * careful version and quietly reintroduce the bug: bundlers substitute the\n * member expression `process.env.NODE_ENV` and nothing else, so in a browser —\n * where the identifier `process` does not exist — the guard would return early\n * while the literal right after it had already been replaced with\n * `\"development\"`.\n *\n * Returns `false` when the read throws, which is the environment that defines\n * neither symbol: a raw service-worker context, a plain\n * `<script type=\"module\">`, a bundler substituting nothing. Staying quiet there\n * is deliberate — a dev-only warning that cannot prove it is in development is\n * better silent than shouting in someone's production console.\n *\n * @returns Whether development-only diagnostics should run.\n *\n * @example\n * if (isDevBuild()) console.warn(\"[my-app] this prop combination does nothing\");\n *\n * @tempest-limits empty-catch — the only thing the read can throw is the\n * environment answering \"not defined\", which is the return value, not an error\n * worth reporting. Logging it would print on every call in exactly the context\n * that has nowhere to print.\n */\nexport function isDevBuild(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return false;\n }\n}\n"],"mappings":"AAkCA,SAAgB,GAAsB,CAClC,GAAI,CACA,OAAA,QAAA,IAAA,WAAgC,YACpC,MAAQ,CACJ,MAAO,EACX,CACJ"}
1
+ {"version":3,"file":"dev-mode.cjs","names":[],"sources":["../../src/utils/dev-mode.ts"],"sourcesContent":["/**\n * Internal, and imported by path (`../utils/dev-mode`) rather than through the\n * `utils` barrel: re-exporting it would make a one-line env read part of the\n * package's public API, with the semver weight that carries, for something no\n * consumer asked for. The three call sites are `<Icon>`, `useStickyBodyWarning`\n * and the `DataTable` dev warnings.\n */\n\n/**\n * Whether the consuming app was built for development.\n *\n * Reads `process.env.NODE_ENV`, which every supported bundler (Vite, webpack,\n * Rspack, Parcel) replaces with a literal **while building the app**. That\n * timing is the whole point: `import.meta.env.DEV` looks equivalent and is not,\n * because Vite replaces it while building *this package*, so a published\n * artifact carries the constant `false` and every guard behind it becomes dead\n * code the app's own dev server can no longer switch on.\n *\n * The expression is written out in full, and the failure is caught rather than\n * guarded against. A `typeof process === \"undefined\"` check would read as the\n * careful version and quietly reintroduce the bug: bundlers substitute the\n * member expression `process.env.NODE_ENV` and nothing else, so in a browser —\n * where the identifier `process` does not exist — the guard would return early\n * while the literal right after it had already been replaced with\n * `\"development\"`.\n *\n * Returns `false` when the read throws, which is the environment that defines\n * neither symbol: a raw service-worker context, a plain\n * `<script type=\"module\">`, a bundler substituting nothing. Staying quiet there\n * is deliberate — a dev-only warning that cannot prove it is in development is\n * better silent than shouting in someone's production console.\n *\n * @returns Whether development-only diagnostics should run.\n *\n * @example\n * if (isDevBuild()) console.warn(\"[my-app] this prop combination does nothing\");\n *\n * @tempest-limits empty-catch — the only thing the read can throw is the\n * environment answering \"not defined\", which is the return value, not an error\n * worth reporting. Logging it would print on every call in exactly the context\n * that has nowhere to print.\n */\nexport function isDevBuild(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return false;\n }\n}\n"],"mappings":"AA0CA,SAAgB,GAAsB,CAClC,GAAI,CACA,OAAA,QAAA,IAAA,WAAgC,YACpC,MAAQ,CACJ,MAAO,EACX,CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev-mode.js","names":[],"sources":["../../src/utils/dev-mode.ts"],"sourcesContent":["/**\n * Whether the consuming app was built for development.\n *\n * Reads `process.env.NODE_ENV`, which every supported bundler (Vite, webpack,\n * Rspack, Parcel) replaces with a literal **while building the app**. That\n * timing is the whole point: `import.meta.env.DEV` looks equivalent and is not,\n * because Vite replaces it while building *this package*, so a published\n * artifact carries the constant `false` and every guard behind it becomes dead\n * code the app's own dev server can no longer switch on.\n *\n * The expression is written out in full, and the failure is caught rather than\n * guarded against. A `typeof process === \"undefined\"` check would read as the\n * careful version and quietly reintroduce the bug: bundlers substitute the\n * member expression `process.env.NODE_ENV` and nothing else, so in a browser —\n * where the identifier `process` does not exist — the guard would return early\n * while the literal right after it had already been replaced with\n * `\"development\"`.\n *\n * Returns `false` when the read throws, which is the environment that defines\n * neither symbol: a raw service-worker context, a plain\n * `<script type=\"module\">`, a bundler substituting nothing. Staying quiet there\n * is deliberate — a dev-only warning that cannot prove it is in development is\n * better silent than shouting in someone's production console.\n *\n * @returns Whether development-only diagnostics should run.\n *\n * @example\n * if (isDevBuild()) console.warn(\"[my-app] this prop combination does nothing\");\n *\n * @tempest-limits empty-catch — the only thing the read can throw is the\n * environment answering \"not defined\", which is the return value, not an error\n * worth reporting. Logging it would print on every call in exactly the context\n * that has nowhere to print.\n */\nexport function isDevBuild(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return false;\n }\n}\n"],"mappings":";AAkCA,SAAgB,IAAsB;CAClC,IAAI;EACA,OAAA,QAAA,IAAA,aAAgC;CACpC,QAAQ;EACJ,OAAO;CACX;AACJ"}
1
+ {"version":3,"file":"dev-mode.js","names":[],"sources":["../../src/utils/dev-mode.ts"],"sourcesContent":["/**\n * Internal, and imported by path (`../utils/dev-mode`) rather than through the\n * `utils` barrel: re-exporting it would make a one-line env read part of the\n * package's public API, with the semver weight that carries, for something no\n * consumer asked for. The three call sites are `<Icon>`, `useStickyBodyWarning`\n * and the `DataTable` dev warnings.\n */\n\n/**\n * Whether the consuming app was built for development.\n *\n * Reads `process.env.NODE_ENV`, which every supported bundler (Vite, webpack,\n * Rspack, Parcel) replaces with a literal **while building the app**. That\n * timing is the whole point: `import.meta.env.DEV` looks equivalent and is not,\n * because Vite replaces it while building *this package*, so a published\n * artifact carries the constant `false` and every guard behind it becomes dead\n * code the app's own dev server can no longer switch on.\n *\n * The expression is written out in full, and the failure is caught rather than\n * guarded against. A `typeof process === \"undefined\"` check would read as the\n * careful version and quietly reintroduce the bug: bundlers substitute the\n * member expression `process.env.NODE_ENV` and nothing else, so in a browser —\n * where the identifier `process` does not exist — the guard would return early\n * while the literal right after it had already been replaced with\n * `\"development\"`.\n *\n * Returns `false` when the read throws, which is the environment that defines\n * neither symbol: a raw service-worker context, a plain\n * `<script type=\"module\">`, a bundler substituting nothing. Staying quiet there\n * is deliberate — a dev-only warning that cannot prove it is in development is\n * better silent than shouting in someone's production console.\n *\n * @returns Whether development-only diagnostics should run.\n *\n * @example\n * if (isDevBuild()) console.warn(\"[my-app] this prop combination does nothing\");\n *\n * @tempest-limits empty-catch — the only thing the read can throw is the\n * environment answering \"not defined\", which is the return value, not an error\n * worth reporting. Logging it would print on every call in exactly the context\n * that has nowhere to print.\n */\nexport function isDevBuild(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return false;\n }\n}\n"],"mappings":";AA0CA,SAAgB,IAAsB;CAClC,IAAI;EACA,OAAA,QAAA,IAAA,aAAgC;CACpC,QAAQ;EACJ,OAAO;CACX;AACJ"}
@@ -1,2 +1,2 @@
1
- var e={get(e,t){if(typeof window>`u`)return t;try{let n=window.localStorage.getItem(e);return n===null?t:JSON.parse(n)}catch{return t}},set(e,t){if(!(typeof window>`u`))try{window.localStorage.setItem(e,JSON.stringify(t))}catch{}},remove(e){if(!(typeof window>`u`))try{window.localStorage.removeItem(e)}catch{}}};exports.storage=e;
1
+ var e={serialize:e=>JSON.stringify(e),deserialize:e=>JSON.parse(e)};function t(e,t){try{return e.serialize(t)}catch{try{return JSON.stringify(t)}catch{return null}}}function n(n=e){return{get(e,t){if(typeof window>`u`)return t;try{let r=window.localStorage.getItem(e);return r===null?t:n.deserialize(r)}catch{return t}},set(e,r){if(typeof window>`u`)return;let i=t(n,r);if(i!==null)try{window.localStorage.setItem(e,i)}catch{}},remove(e){if(!(typeof window>`u`))try{window.localStorage.removeItem(e)}catch{}}}}var r=n();exports.createJsonStorage=n,exports.storage=r;
2
2
  //# sourceMappingURL=storage.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.cjs","names":[],"sources":["../../src/utils/storage.ts"],"sourcesContent":["/**\n * Typed wrapper around `localStorage` that JSON-encodes values and\n * silently handles environments where storage is unavailable (SSR, private mode).\n *\n * @tempest-limits empty-catch — every method here is best-effort by contract:\n * `localStorage` throws on quota exhaustion, in Safari private mode, and when a\n * cross-origin frame has storage blocked. A caller persisting a preference has no\n * recovery to run and no user-facing message to show, so the write is dropped and\n * the app keeps the value in memory for the session.\n */\nexport const storage = {\n get<T>(key: string, fallback: T): T {\n if (typeof window === \"undefined\") return fallback;\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? fallback : (JSON.parse(raw) as T);\n } catch {\n return fallback;\n }\n },\n set<T>(key: string, value: T): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* empty */\n }\n },\n remove(key: string): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.removeItem(key);\n } catch {\n /* empty */\n }\n },\n};\n"],"mappings":"AAUA,IAAa,EAAU,CACnB,IAAO,EAAa,EAAgB,CAChC,GAAI,OAAO,OAAW,IAAa,OAAO,EAC1C,GAAI,CACA,IAAM,EAAM,OAAO,aAAa,QAAQ,CAAG,EAC3C,OAAO,IAAQ,KAAO,EAAY,KAAK,MAAM,CAAG,CACpD,MAAQ,CACJ,OAAO,CACX,CACJ,EACA,IAAO,EAAa,EAAgB,CAC5B,YAAO,OAAW,KACtB,GAAI,CACA,OAAO,aAAa,QAAQ,EAAK,KAAK,UAAU,CAAK,CAAC,CAC1D,MAAQ,CAER,CACJ,EACA,OAAO,EAAmB,CAClB,YAAO,OAAW,KACtB,GAAI,CACA,OAAO,aAAa,WAAW,CAAG,CACtC,MAAQ,CAER,CACJ,CACJ"}
1
+ {"version":3,"file":"storage.cjs","names":[],"sources":["../../src/utils/storage.ts"],"sourcesContent":["/** How a {@link createJsonStorage} store turns values into text and back. */\nexport interface StorageCodec {\n /** Encode a value for storage. */\n serialize: <T>(value: T) => string;\n /** Decode a stored string. */\n deserialize: <T>(raw: string) => T;\n}\n\n/** The surface every store built by {@link createJsonStorage} exposes. */\nexport interface JsonStorage {\n /**\n * Read and decode a key.\n *\n * @typeParam T - The expected value shape.\n * @param key - Storage key.\n * @param fallback - Returned when the key is absent, unreadable, or corrupt.\n * @returns The stored value, or `fallback`.\n */\n get<T>(key: string, fallback: T): T;\n /**\n * Encode and write a key.\n *\n * @typeParam T - The value being stored.\n * @param key - Storage key.\n * @param value - Any value the codec can represent.\n */\n set<T>(key: string, value: T): void;\n /**\n * Delete a key.\n *\n * @param key - Storage key.\n */\n remove(key: string): void;\n}\n\nconst jsonCodec: StorageCodec = {\n serialize: (value) => JSON.stringify(value),\n deserialize: (raw) => JSON.parse(raw),\n};\n\n/**\n * Encode with the codec, degrading to plain JSON when the codec itself fails.\n *\n * A codec that throws — a compressor running out of room on a huge value —\n * should cost size, not the record: a slightly larger row still loads, an absent\n * one does not. `null` means not even JSON could represent the value, which is\n * the one case where dropping the write is the only option left.\n *\n * @param codec - The store's codec.\n * @param value - The value to encode.\n * @returns The encoded string, or `null` when the value cannot be represented.\n */\nfunction encode<T>(codec: StorageCodec, value: T): string | null {\n try {\n return codec.serialize(value);\n } catch {\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n }\n}\n\n/**\n * Build a typed `localStorage` wrapper around a codec.\n *\n * One implementation behind every store the SDK ships, so they cannot drift in\n * surface. {@link storage} and {@link compressedStorage} are both this function —\n * before it, the compressed one was a hand-written copy of the same guards and\n * had no `remove`, while its own docstring promised the two were interchangeable\n * at the call site. They were not, and the promise failed exactly where somebody\n * followed it.\n *\n * @example\n * const session = createJsonStorage();\n * session.set(\"draft\", { title: \"Sem título\" });\n *\n * @example\n * const packed = createJsonStorage(compressedStorageCodec);\n *\n * @param codec - Encoder pair. Defaults to plain JSON.\n * @returns A store with `get` / `set` / `remove`.\n *\n * @tempest-limits empty-catch — every method is best-effort by contract:\n * `localStorage` throws on quota exhaustion, in Safari private mode, and when a\n * cross-origin frame has storage blocked. A caller persisting a preference has no\n * recovery to run and no user-facing message to show, so the write is dropped and\n * the app keeps the value in memory for the session.\n */\nexport function createJsonStorage(codec: StorageCodec = jsonCodec): JsonStorage {\n return {\n get<T>(key: string, fallback: T): T {\n if (typeof window === \"undefined\") return fallback;\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? fallback : codec.deserialize<T>(raw);\n } catch {\n return fallback;\n }\n },\n\n set<T>(key: string, value: T): void {\n if (typeof window === \"undefined\") return;\n const encoded = encode(codec, value);\n if (encoded === null) return;\n try {\n window.localStorage.setItem(key, encoded);\n } catch {\n /* empty */\n }\n },\n\n remove(key: string): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.removeItem(key);\n } catch {\n /* empty */\n }\n },\n };\n}\n\n/**\n * Typed wrapper around `localStorage` that JSON-encodes values and silently\n * handles environments where storage is unavailable (SSR, private mode).\n */\nexport const storage: JsonStorage = createJsonStorage();\n"],"mappings":"AAmCA,IAAM,EAA0B,CAC5B,UAAY,GAAU,KAAK,UAAU,CAAK,EAC1C,YAAc,GAAQ,KAAK,MAAM,CAAG,CACxC,EAcA,SAAS,EAAU,EAAqB,EAAyB,CAC7D,GAAI,CACA,OAAO,EAAM,UAAU,CAAK,CAChC,MAAQ,CACJ,GAAI,CACA,OAAO,KAAK,UAAU,CAAK,CAC/B,MAAQ,CACJ,OAAO,IACX,CACJ,CACJ,CA4BA,SAAgB,EAAkB,EAAsB,EAAwB,CAC5E,MAAO,CACH,IAAO,EAAa,EAAgB,CAChC,GAAI,OAAO,OAAW,IAAa,OAAO,EAC1C,GAAI,CACA,IAAM,EAAM,OAAO,aAAa,QAAQ,CAAG,EAC3C,OAAO,IAAQ,KAAO,EAAW,EAAM,YAAe,CAAG,CAC7D,MAAQ,CACJ,OAAO,CACX,CACJ,EAEA,IAAO,EAAa,EAAgB,CAChC,GAAI,OAAO,OAAW,IAAa,OACnC,IAAM,EAAU,EAAO,EAAO,CAAK,EAC/B,OAAY,KAChB,GAAI,CACA,OAAO,aAAa,QAAQ,EAAK,CAAO,CAC5C,MAAQ,CAER,CACJ,EAEA,OAAO,EAAmB,CAClB,YAAO,OAAW,KACtB,GAAI,CACA,OAAO,aAAa,WAAW,CAAG,CACtC,MAAQ,CAER,CACJ,CACJ,CACJ,CAMA,IAAa,EAAuB,EAAkB"}
@@ -1,26 +1,46 @@
1
1
  //#region src/utils/storage.ts
2
2
  var e = {
3
- get(e, t) {
4
- if (typeof window > "u") return t;
3
+ serialize: (e) => JSON.stringify(e),
4
+ deserialize: (e) => JSON.parse(e)
5
+ };
6
+ function t(e, t) {
7
+ try {
8
+ return e.serialize(t);
9
+ } catch {
5
10
  try {
6
- let n = window.localStorage.getItem(e);
7
- return n === null ? t : JSON.parse(n);
11
+ return JSON.stringify(t);
8
12
  } catch {
9
- return t;
13
+ return null;
10
14
  }
11
- },
12
- set(e, t) {
13
- if (!(typeof window > "u")) try {
14
- window.localStorage.setItem(e, JSON.stringify(t));
15
- } catch {}
16
- },
17
- remove(e) {
18
- if (!(typeof window > "u")) try {
19
- window.localStorage.removeItem(e);
20
- } catch {}
21
15
  }
22
- };
16
+ }
17
+ function n(n = e) {
18
+ return {
19
+ get(e, t) {
20
+ if (typeof window > "u") return t;
21
+ try {
22
+ let r = window.localStorage.getItem(e);
23
+ return r === null ? t : n.deserialize(r);
24
+ } catch {
25
+ return t;
26
+ }
27
+ },
28
+ set(e, r) {
29
+ if (typeof window > "u") return;
30
+ let i = t(n, r);
31
+ if (i !== null) try {
32
+ window.localStorage.setItem(e, i);
33
+ } catch {}
34
+ },
35
+ remove(e) {
36
+ if (!(typeof window > "u")) try {
37
+ window.localStorage.removeItem(e);
38
+ } catch {}
39
+ }
40
+ };
41
+ }
42
+ var r = n();
23
43
  //#endregion
24
- export { e as storage };
44
+ export { n as createJsonStorage, r as storage };
25
45
 
26
46
  //# sourceMappingURL=storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","names":[],"sources":["../../src/utils/storage.ts"],"sourcesContent":["/**\n * Typed wrapper around `localStorage` that JSON-encodes values and\n * silently handles environments where storage is unavailable (SSR, private mode).\n *\n * @tempest-limits empty-catch — every method here is best-effort by contract:\n * `localStorage` throws on quota exhaustion, in Safari private mode, and when a\n * cross-origin frame has storage blocked. A caller persisting a preference has no\n * recovery to run and no user-facing message to show, so the write is dropped and\n * the app keeps the value in memory for the session.\n */\nexport const storage = {\n get<T>(key: string, fallback: T): T {\n if (typeof window === \"undefined\") return fallback;\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? fallback : (JSON.parse(raw) as T);\n } catch {\n return fallback;\n }\n },\n set<T>(key: string, value: T): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* empty */\n }\n },\n remove(key: string): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.removeItem(key);\n } catch {\n /* empty */\n }\n },\n};\n"],"mappings":";AAUA,IAAa,IAAU;CACnB,IAAO,GAAa,GAAgB;EAChC,IAAI,OAAO,SAAW,KAAa,OAAO;EAC1C,IAAI;GACA,IAAM,IAAM,OAAO,aAAa,QAAQ,CAAG;GAC3C,OAAO,MAAQ,OAAO,IAAY,KAAK,MAAM,CAAG;EACpD,QAAQ;GACJ,OAAO;EACX;CACJ;CACA,IAAO,GAAa,GAAgB;EAC5B,aAAO,SAAW,MACtB,IAAI;GACA,OAAO,aAAa,QAAQ,GAAK,KAAK,UAAU,CAAK,CAAC;EAC1D,QAAQ,CAER;CACJ;CACA,OAAO,GAAmB;EAClB,aAAO,SAAW,MACtB,IAAI;GACA,OAAO,aAAa,WAAW,CAAG;EACtC,QAAQ,CAER;CACJ;AACJ"}
1
+ {"version":3,"file":"storage.js","names":[],"sources":["../../src/utils/storage.ts"],"sourcesContent":["/** How a {@link createJsonStorage} store turns values into text and back. */\nexport interface StorageCodec {\n /** Encode a value for storage. */\n serialize: <T>(value: T) => string;\n /** Decode a stored string. */\n deserialize: <T>(raw: string) => T;\n}\n\n/** The surface every store built by {@link createJsonStorage} exposes. */\nexport interface JsonStorage {\n /**\n * Read and decode a key.\n *\n * @typeParam T - The expected value shape.\n * @param key - Storage key.\n * @param fallback - Returned when the key is absent, unreadable, or corrupt.\n * @returns The stored value, or `fallback`.\n */\n get<T>(key: string, fallback: T): T;\n /**\n * Encode and write a key.\n *\n * @typeParam T - The value being stored.\n * @param key - Storage key.\n * @param value - Any value the codec can represent.\n */\n set<T>(key: string, value: T): void;\n /**\n * Delete a key.\n *\n * @param key - Storage key.\n */\n remove(key: string): void;\n}\n\nconst jsonCodec: StorageCodec = {\n serialize: (value) => JSON.stringify(value),\n deserialize: (raw) => JSON.parse(raw),\n};\n\n/**\n * Encode with the codec, degrading to plain JSON when the codec itself fails.\n *\n * A codec that throws — a compressor running out of room on a huge value —\n * should cost size, not the record: a slightly larger row still loads, an absent\n * one does not. `null` means not even JSON could represent the value, which is\n * the one case where dropping the write is the only option left.\n *\n * @param codec - The store's codec.\n * @param value - The value to encode.\n * @returns The encoded string, or `null` when the value cannot be represented.\n */\nfunction encode<T>(codec: StorageCodec, value: T): string | null {\n try {\n return codec.serialize(value);\n } catch {\n try {\n return JSON.stringify(value);\n } catch {\n return null;\n }\n }\n}\n\n/**\n * Build a typed `localStorage` wrapper around a codec.\n *\n * One implementation behind every store the SDK ships, so they cannot drift in\n * surface. {@link storage} and {@link compressedStorage} are both this function —\n * before it, the compressed one was a hand-written copy of the same guards and\n * had no `remove`, while its own docstring promised the two were interchangeable\n * at the call site. They were not, and the promise failed exactly where somebody\n * followed it.\n *\n * @example\n * const session = createJsonStorage();\n * session.set(\"draft\", { title: \"Sem título\" });\n *\n * @example\n * const packed = createJsonStorage(compressedStorageCodec);\n *\n * @param codec - Encoder pair. Defaults to plain JSON.\n * @returns A store with `get` / `set` / `remove`.\n *\n * @tempest-limits empty-catch — every method is best-effort by contract:\n * `localStorage` throws on quota exhaustion, in Safari private mode, and when a\n * cross-origin frame has storage blocked. A caller persisting a preference has no\n * recovery to run and no user-facing message to show, so the write is dropped and\n * the app keeps the value in memory for the session.\n */\nexport function createJsonStorage(codec: StorageCodec = jsonCodec): JsonStorage {\n return {\n get<T>(key: string, fallback: T): T {\n if (typeof window === \"undefined\") return fallback;\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? fallback : codec.deserialize<T>(raw);\n } catch {\n return fallback;\n }\n },\n\n set<T>(key: string, value: T): void {\n if (typeof window === \"undefined\") return;\n const encoded = encode(codec, value);\n if (encoded === null) return;\n try {\n window.localStorage.setItem(key, encoded);\n } catch {\n /* empty */\n }\n },\n\n remove(key: string): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.removeItem(key);\n } catch {\n /* empty */\n }\n },\n };\n}\n\n/**\n * Typed wrapper around `localStorage` that JSON-encodes values and silently\n * handles environments where storage is unavailable (SSR, private mode).\n */\nexport const storage: JsonStorage = createJsonStorage();\n"],"mappings":";AAmCA,IAAM,IAA0B;CAC5B,YAAY,MAAU,KAAK,UAAU,CAAK;CAC1C,cAAc,MAAQ,KAAK,MAAM,CAAG;AACxC;AAcA,SAAS,EAAU,GAAqB,GAAyB;CAC7D,IAAI;EACA,OAAO,EAAM,UAAU,CAAK;CAChC,QAAQ;EACJ,IAAI;GACA,OAAO,KAAK,UAAU,CAAK;EAC/B,QAAQ;GACJ,OAAO;EACX;CACJ;AACJ;AA4BA,SAAgB,EAAkB,IAAsB,GAAwB;CAC5E,OAAO;EACH,IAAO,GAAa,GAAgB;GAChC,IAAI,OAAO,SAAW,KAAa,OAAO;GAC1C,IAAI;IACA,IAAM,IAAM,OAAO,aAAa,QAAQ,CAAG;IAC3C,OAAO,MAAQ,OAAO,IAAW,EAAM,YAAe,CAAG;GAC7D,QAAQ;IACJ,OAAO;GACX;EACJ;EAEA,IAAO,GAAa,GAAgB;GAChC,IAAI,OAAO,SAAW,KAAa;GACnC,IAAM,IAAU,EAAO,GAAO,CAAK;GAC/B,UAAY,MAChB,IAAI;IACA,OAAO,aAAa,QAAQ,GAAK,CAAO;GAC5C,QAAQ,CAER;EACJ;EAEA,OAAO,GAAmB;GAClB,aAAO,SAAW,MACtB,IAAI;IACA,OAAO,aAAa,WAAW,CAAG;GACtC,QAAQ,CAER;EACJ;CACJ;AACJ;AAMA,IAAa,IAAuB,EAAkB"}
@@ -1,2 +1,2 @@
1
- const e=require("../audio/media-access.cjs");let t=require("react");var n={video:{facingMode:{ideal:`environment`},width:{ideal:1920},height:{ideal:1080}},audio:!1};function r({kind:e,message:t}){return{kind:e===`not-found`?`no-camera`:e,message:t}}function i(t){return r(e.classifyMediaError(t,`camera`))}function a(a={}){let[o,s]=(0,t.useState)(`loading`),[c,l]=(0,t.useState)(null),[u,d]=(0,t.useState)(null),[f,p]=(0,t.useState)(0),m=(0,t.useRef)(null),h=(0,t.useRef)(a.constraints??n);(0,t.useEffect)(()=>{h.current=a.constraints??n},[a.constraints]);let g=a.enabled??!0;return(0,t.useEffect)(()=>{let t=!1,n=null,a=null;async function o(){if(!g){s(`idle`),l(null);return}if(s(`loading`),l(null),typeof navigator>`u`||!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!=`function`){t||(l(r(e.missingCaptureApiError(`camera`))),s(`error`));return}try{if(n=await navigator.mediaDevices.getUserMedia(h.current),t){n.getTracks().forEach(e=>e.stop());return}let e=m.current;if(!e){n.getTracks().forEach(e=>e.stop());return}a=e,e.srcObject=n,d(n),await e.play().catch(()=>void 0),t||s(`ready`)}catch(e){t||(l(i(e)),s(`error`))}}return o(),()=>{t=!0,n&&n.getTracks().forEach(e=>e.stop()),a&&(a.srcObject=null),d(null)}},[f,g]),{status:o,error:c,videoRef:m,stream:u,retry:()=>p(e=>e+1)}}exports.useCameraStream=a;
1
+ const e=require("../hooks/use-latest-ref.cjs"),t=require("../audio/media-access.cjs");let n=require("react");var r={video:{facingMode:{ideal:`environment`},width:{ideal:1920},height:{ideal:1080}},audio:!1};function i({kind:e,message:t}){return{kind:e===`not-found`?`no-camera`:e,message:t}}function a(e){return i(t.classifyMediaError(e,`camera`))}function o(o={}){let[s,c]=(0,n.useState)(`loading`),[l,u]=(0,n.useState)(null),[d,f]=(0,n.useState)(null),[p,m]=(0,n.useState)(0),h=(0,n.useRef)(null),g=e.useLatestRef(o.constraints??r),_=o.enabled??!0;return(0,n.useEffect)(()=>{let e=!1,n=null,r=null;async function o(){if(!_){c(`idle`),u(null);return}if(c(`loading`),u(null),typeof navigator>`u`||!navigator.mediaDevices||typeof navigator.mediaDevices.getUserMedia!=`function`){e||(u(i(t.missingCaptureApiError(`camera`))),c(`error`));return}try{if(n=await navigator.mediaDevices.getUserMedia(g.current),e){n.getTracks().forEach(e=>e.stop());return}let t=h.current;if(!t){n.getTracks().forEach(e=>e.stop());return}r=t,t.srcObject=n,f(n),await t.play().catch(()=>void 0),e||c(`ready`)}catch(t){e||(u(a(t)),c(`error`))}}return o(),()=>{e=!0,n&&n.getTracks().forEach(e=>e.stop()),r&&(r.srcObject=null),f(null)}},[p,_,g]),{status:s,error:l,videoRef:h,stream:d,retry:()=>m(e=>e+1)}}exports.useCameraStream=o;
2
2
  //# sourceMappingURL=use-camera-stream.cjs.map