tempest-react-sdk 0.57.0 → 0.59.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 (396) hide show
  1. package/README.md +14 -2
  2. package/bin/lib/css/findings.mjs +1 -0
  3. package/bin/lib/css/semantic.mjs +70 -6
  4. package/bin/lib/css/semantic.test.mjs +52 -1
  5. package/bin/lib/icons/generate.test.mjs +4 -4
  6. package/dist/br/geocode.cjs +1 -1
  7. package/dist/br/geocode.cjs.map +1 -1
  8. package/dist/br/geocode.js +1 -1
  9. package/dist/br/geocode.js.map +1 -1
  10. package/dist/capture/use-barcode-scanner.cjs +1 -1
  11. package/dist/capture/use-barcode-scanner.cjs.map +1 -1
  12. package/dist/capture/use-barcode-scanner.js +1 -1
  13. package/dist/capture/use-barcode-scanner.js.map +1 -1
  14. package/dist/components/AIChat/AIChat.cjs +1 -1
  15. package/dist/components/AIChat/AIChat.cjs.map +1 -1
  16. package/dist/components/AIChat/AIChat.js +1 -1
  17. package/dist/components/AIChat/AIChat.js.map +1 -1
  18. package/dist/components/AIChat/AIChatTurn.cjs +1 -1
  19. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
  20. package/dist/components/AIChat/AIChatTurn.js +1 -1
  21. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  22. package/dist/components/Alert/Alert.module.cjs.map +1 -1
  23. package/dist/components/Alert/Alert.module.js.map +1 -1
  24. package/dist/components/AppBar/use-sticky-body-warning.cjs +1 -1
  25. package/dist/components/AppBar/use-sticky-body-warning.cjs.map +1 -1
  26. package/dist/components/AppBar/use-sticky-body-warning.js +1 -1
  27. package/dist/components/AppBar/use-sticky-body-warning.js.map +1 -1
  28. package/dist/components/AudioPlayer/AudioPlayer.cjs +1 -1
  29. package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
  30. package/dist/components/AudioPlayer/AudioPlayer.js +2 -2
  31. package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
  32. package/dist/components/AudioRecorder/AudioRecorder.cjs +1 -1
  33. package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
  34. package/dist/components/AudioRecorder/AudioRecorder.js +1 -1
  35. package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
  36. package/dist/components/Badge/Badge.module.cjs.map +1 -1
  37. package/dist/components/Badge/Badge.module.js.map +1 -1
  38. package/dist/components/BarList/BarList.module.cjs.map +1 -1
  39. package/dist/components/BarList/BarList.module.js.map +1 -1
  40. package/dist/components/BottomSheet/BottomSheet.module.cjs.map +1 -1
  41. package/dist/components/BottomSheet/BottomSheet.module.js.map +1 -1
  42. package/dist/components/Chat/Chat.cjs +1 -1
  43. package/dist/components/Chat/Chat.cjs.map +1 -1
  44. package/dist/components/Chat/Chat.js +1 -1
  45. package/dist/components/Chat/Chat.js.map +1 -1
  46. package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
  47. package/dist/components/DataTable/DataTable.module.js.map +1 -1
  48. package/dist/components/Dropzone/Dropzone.module.cjs.map +1 -1
  49. package/dist/components/Dropzone/Dropzone.module.js.map +1 -1
  50. package/dist/components/ErrorText/ErrorText.module.cjs.map +1 -1
  51. package/dist/components/ErrorText/ErrorText.module.js.map +1 -1
  52. package/dist/components/FilterBar/FilterBar.cjs +1 -1
  53. package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
  54. package/dist/components/FilterBar/FilterBar.js +1 -1
  55. package/dist/components/FilterBar/FilterBar.js.map +1 -1
  56. package/dist/components/FilterBar/filter-apply.cjs +1 -1
  57. package/dist/components/FilterBar/filter-apply.cjs.map +1 -1
  58. package/dist/components/FilterBar/filter-apply.js +1 -1
  59. package/dist/components/FilterBar/filter-apply.js.map +1 -1
  60. package/dist/components/ImageCropper/ImageCropper.cjs +1 -1
  61. package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
  62. package/dist/components/ImageCropper/ImageCropper.js +1 -1
  63. package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
  64. package/dist/components/Markdown/Markdown.module.cjs.map +1 -1
  65. package/dist/components/Markdown/Markdown.module.js.map +1 -1
  66. package/dist/components/PasswordInput/PasswordInput.module.cjs.map +1 -1
  67. package/dist/components/PasswordInput/PasswordInput.module.js.map +1 -1
  68. package/dist/components/SegmentedControl/SegmentedControl.module.cjs.map +1 -1
  69. package/dist/components/SegmentedControl/SegmentedControl.module.js.map +1 -1
  70. package/dist/components/Sidebar/Sidebar.module.cjs.map +1 -1
  71. package/dist/components/Sidebar/Sidebar.module.js.map +1 -1
  72. package/dist/components/StepperInput/StepperInput.module.cjs.map +1 -1
  73. package/dist/components/StepperInput/StepperInput.module.js.map +1 -1
  74. package/dist/components/Tag/Tag.module.cjs.map +1 -1
  75. package/dist/components/Tag/Tag.module.js.map +1 -1
  76. package/dist/components/Timeline/Timeline.module.cjs.map +1 -1
  77. package/dist/components/Timeline/Timeline.module.js.map +1 -1
  78. package/dist/components/Toggle/Toggle.module.cjs.map +1 -1
  79. package/dist/components/Toggle/Toggle.module.js.map +1 -1
  80. package/dist/components/ToggleGroup/ToggleGroup.module.cjs.map +1 -1
  81. package/dist/components/ToggleGroup/ToggleGroup.module.js.map +1 -1
  82. package/dist/components/VideoPlayer/VideoPlayer.cjs +1 -1
  83. package/dist/components/VideoPlayer/VideoPlayer.cjs.map +1 -1
  84. package/dist/components/VideoPlayer/VideoPlayer.js +2 -2
  85. package/dist/components/VideoPlayer/VideoPlayer.js.map +1 -1
  86. package/dist/components/VirtualTable/VirtualTable.cjs +1 -1
  87. package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
  88. package/dist/components/VirtualTable/VirtualTable.js +1 -1
  89. package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
  90. package/dist/feature-flags/growthbook-adapter.cjs +1 -1
  91. package/dist/feature-flags/growthbook-adapter.cjs.map +1 -1
  92. package/dist/feature-flags/growthbook-adapter.js +1 -1
  93. package/dist/feature-flags/growthbook-adapter.js.map +1 -1
  94. package/dist/hooks/use-focus-trap.cjs +1 -1
  95. package/dist/hooks/use-focus-trap.cjs.map +1 -1
  96. package/dist/hooks/use-focus-trap.js +1 -1
  97. package/dist/hooks/use-focus-trap.js.map +1 -1
  98. package/dist/hooks/use-push-to-talk.cjs +1 -1
  99. package/dist/hooks/use-push-to-talk.cjs.map +1 -1
  100. package/dist/hooks/use-push-to-talk.js +1 -1
  101. package/dist/hooks/use-push-to-talk.js.map +1 -1
  102. package/dist/http/describe-api-error.cjs +1 -1
  103. package/dist/http/describe-api-error.cjs.map +1 -1
  104. package/dist/http/describe-api-error.js +12 -8
  105. package/dist/http/describe-api-error.js.map +1 -1
  106. package/dist/http/errors.cjs +1 -1
  107. package/dist/http/errors.cjs.map +1 -1
  108. package/dist/http/errors.js +21 -16
  109. package/dist/http/errors.js.map +1 -1
  110. package/dist/http/resumable-upload.cjs +1 -1
  111. package/dist/http/resumable-upload.cjs.map +1 -1
  112. package/dist/http/resumable-upload.js +1 -1
  113. package/dist/http/resumable-upload.js.map +1 -1
  114. package/dist/icons/generated/aliases.cjs +1 -1
  115. package/dist/icons/generated/aliases.cjs.map +1 -1
  116. package/dist/icons/generated/aliases.js +1 -0
  117. package/dist/icons/generated/aliases.js.map +1 -1
  118. package/dist/icons/generated/icon-names.cjs +1 -1
  119. package/dist/icons/generated/icon-names.cjs.map +1 -1
  120. package/dist/icons/generated/icon-names.js +1 -1
  121. package/dist/icons/generated/icon-names.js.map +1 -1
  122. package/dist/icons/generated/loaders.cjs +1 -1
  123. package/dist/icons/generated/loaders.cjs.map +1 -1
  124. package/dist/icons/generated/loaders.js +48 -42
  125. package/dist/icons/generated/loaders.js.map +1 -1
  126. package/dist/icons/generated/shard-02.cjs +1 -1
  127. package/dist/icons/generated/shard-02.cjs.map +1 -1
  128. package/dist/icons/generated/shard-02.js +20 -20
  129. package/dist/icons/generated/shard-02.js.map +1 -1
  130. package/dist/icons/generated/shard-03.cjs +1 -1
  131. package/dist/icons/generated/shard-03.cjs.map +1 -1
  132. package/dist/icons/generated/shard-03.js +41 -41
  133. package/dist/icons/generated/shard-03.js.map +1 -1
  134. package/dist/icons/generated/shard-04.cjs +1 -1
  135. package/dist/icons/generated/shard-04.cjs.map +1 -1
  136. package/dist/icons/generated/shard-04.js +41 -41
  137. package/dist/icons/generated/shard-04.js.map +1 -1
  138. package/dist/icons/generated/shard-05.cjs +1 -1
  139. package/dist/icons/generated/shard-05.cjs.map +1 -1
  140. package/dist/icons/generated/shard-05.js +41 -41
  141. package/dist/icons/generated/shard-05.js.map +1 -1
  142. package/dist/icons/generated/shard-06.cjs +1 -1
  143. package/dist/icons/generated/shard-06.cjs.map +1 -1
  144. package/dist/icons/generated/shard-06.js +41 -41
  145. package/dist/icons/generated/shard-06.js.map +1 -1
  146. package/dist/icons/generated/shard-07.cjs +1 -1
  147. package/dist/icons/generated/shard-07.cjs.map +1 -1
  148. package/dist/icons/generated/shard-07.js +41 -41
  149. package/dist/icons/generated/shard-07.js.map +1 -1
  150. package/dist/icons/generated/shard-08.cjs +1 -1
  151. package/dist/icons/generated/shard-08.cjs.map +1 -1
  152. package/dist/icons/generated/shard-08.js +41 -41
  153. package/dist/icons/generated/shard-08.js.map +1 -1
  154. package/dist/icons/generated/shard-09.cjs +1 -1
  155. package/dist/icons/generated/shard-09.cjs.map +1 -1
  156. package/dist/icons/generated/shard-09.js +41 -41
  157. package/dist/icons/generated/shard-09.js.map +1 -1
  158. package/dist/icons/generated/shard-10.cjs +1 -1
  159. package/dist/icons/generated/shard-10.cjs.map +1 -1
  160. package/dist/icons/generated/shard-10.js +41 -41
  161. package/dist/icons/generated/shard-10.js.map +1 -1
  162. package/dist/icons/generated/shard-11.cjs +1 -1
  163. package/dist/icons/generated/shard-11.cjs.map +1 -1
  164. package/dist/icons/generated/shard-11.js +41 -41
  165. package/dist/icons/generated/shard-11.js.map +1 -1
  166. package/dist/icons/generated/shard-12.cjs +1 -1
  167. package/dist/icons/generated/shard-12.cjs.map +1 -1
  168. package/dist/icons/generated/shard-12.js +41 -41
  169. package/dist/icons/generated/shard-12.js.map +1 -1
  170. package/dist/icons/generated/shard-13.cjs +1 -1
  171. package/dist/icons/generated/shard-13.cjs.map +1 -1
  172. package/dist/icons/generated/shard-13.js +41 -41
  173. package/dist/icons/generated/shard-13.js.map +1 -1
  174. package/dist/icons/generated/shard-14.cjs +1 -1
  175. package/dist/icons/generated/shard-14.cjs.map +1 -1
  176. package/dist/icons/generated/shard-14.js +41 -41
  177. package/dist/icons/generated/shard-14.js.map +1 -1
  178. package/dist/icons/generated/shard-15.cjs +1 -1
  179. package/dist/icons/generated/shard-15.cjs.map +1 -1
  180. package/dist/icons/generated/shard-15.js +41 -41
  181. package/dist/icons/generated/shard-15.js.map +1 -1
  182. package/dist/icons/generated/shard-16.cjs +1 -1
  183. package/dist/icons/generated/shard-16.cjs.map +1 -1
  184. package/dist/icons/generated/shard-16.js +41 -41
  185. package/dist/icons/generated/shard-16.js.map +1 -1
  186. package/dist/icons/generated/shard-17.cjs +1 -1
  187. package/dist/icons/generated/shard-17.cjs.map +1 -1
  188. package/dist/icons/generated/shard-17.js +41 -41
  189. package/dist/icons/generated/shard-17.js.map +1 -1
  190. package/dist/icons/generated/shard-18.cjs +1 -1
  191. package/dist/icons/generated/shard-18.cjs.map +1 -1
  192. package/dist/icons/generated/shard-18.js +41 -41
  193. package/dist/icons/generated/shard-18.js.map +1 -1
  194. package/dist/icons/generated/shard-19.cjs +1 -1
  195. package/dist/icons/generated/shard-19.cjs.map +1 -1
  196. package/dist/icons/generated/shard-19.js +41 -41
  197. package/dist/icons/generated/shard-19.js.map +1 -1
  198. package/dist/icons/generated/shard-20.cjs +1 -1
  199. package/dist/icons/generated/shard-20.cjs.map +1 -1
  200. package/dist/icons/generated/shard-20.js +41 -41
  201. package/dist/icons/generated/shard-20.js.map +1 -1
  202. package/dist/icons/generated/shard-21.cjs +1 -1
  203. package/dist/icons/generated/shard-21.cjs.map +1 -1
  204. package/dist/icons/generated/shard-21.js +41 -41
  205. package/dist/icons/generated/shard-21.js.map +1 -1
  206. package/dist/icons/generated/shard-22.cjs +1 -1
  207. package/dist/icons/generated/shard-22.cjs.map +1 -1
  208. package/dist/icons/generated/shard-22.js +41 -41
  209. package/dist/icons/generated/shard-22.js.map +1 -1
  210. package/dist/icons/generated/shard-23.cjs +1 -1
  211. package/dist/icons/generated/shard-23.cjs.map +1 -1
  212. package/dist/icons/generated/shard-23.js +41 -41
  213. package/dist/icons/generated/shard-23.js.map +1 -1
  214. package/dist/icons/generated/shard-24.cjs +1 -1
  215. package/dist/icons/generated/shard-24.cjs.map +1 -1
  216. package/dist/icons/generated/shard-24.js +41 -41
  217. package/dist/icons/generated/shard-24.js.map +1 -1
  218. package/dist/icons/generated/shard-25.cjs +1 -1
  219. package/dist/icons/generated/shard-25.cjs.map +1 -1
  220. package/dist/icons/generated/shard-25.js +41 -41
  221. package/dist/icons/generated/shard-25.js.map +1 -1
  222. package/dist/icons/generated/shard-26.cjs +1 -1
  223. package/dist/icons/generated/shard-26.cjs.map +1 -1
  224. package/dist/icons/generated/shard-26.js +41 -41
  225. package/dist/icons/generated/shard-26.js.map +1 -1
  226. package/dist/icons/generated/shard-27.cjs +1 -1
  227. package/dist/icons/generated/shard-27.cjs.map +1 -1
  228. package/dist/icons/generated/shard-27.js +41 -41
  229. package/dist/icons/generated/shard-27.js.map +1 -1
  230. package/dist/icons/generated/shard-28.cjs +1 -1
  231. package/dist/icons/generated/shard-28.cjs.map +1 -1
  232. package/dist/icons/generated/shard-28.js +41 -41
  233. package/dist/icons/generated/shard-28.js.map +1 -1
  234. package/dist/icons/generated/shard-29.cjs +1 -1
  235. package/dist/icons/generated/shard-29.cjs.map +1 -1
  236. package/dist/icons/generated/shard-29.js +41 -41
  237. package/dist/icons/generated/shard-29.js.map +1 -1
  238. package/dist/icons/generated/shard-30.cjs +1 -1
  239. package/dist/icons/generated/shard-30.cjs.map +1 -1
  240. package/dist/icons/generated/shard-30.js +41 -41
  241. package/dist/icons/generated/shard-30.js.map +1 -1
  242. package/dist/icons/generated/shard-31.cjs +1 -1
  243. package/dist/icons/generated/shard-31.cjs.map +1 -1
  244. package/dist/icons/generated/shard-31.js +41 -41
  245. package/dist/icons/generated/shard-31.js.map +1 -1
  246. package/dist/icons/generated/shard-32.cjs +1 -1
  247. package/dist/icons/generated/shard-32.cjs.map +1 -1
  248. package/dist/icons/generated/shard-32.js +41 -41
  249. package/dist/icons/generated/shard-32.js.map +1 -1
  250. package/dist/icons/generated/shard-33.cjs +1 -1
  251. package/dist/icons/generated/shard-33.cjs.map +1 -1
  252. package/dist/icons/generated/shard-33.js +41 -41
  253. package/dist/icons/generated/shard-33.js.map +1 -1
  254. package/dist/icons/generated/shard-34.cjs +1 -1
  255. package/dist/icons/generated/shard-34.cjs.map +1 -1
  256. package/dist/icons/generated/shard-34.js +41 -41
  257. package/dist/icons/generated/shard-34.js.map +1 -1
  258. package/dist/icons/generated/shard-35.cjs +1 -1
  259. package/dist/icons/generated/shard-35.cjs.map +1 -1
  260. package/dist/icons/generated/shard-35.js +41 -41
  261. package/dist/icons/generated/shard-35.js.map +1 -1
  262. package/dist/icons/generated/shard-36.cjs +1 -1
  263. package/dist/icons/generated/shard-36.cjs.map +1 -1
  264. package/dist/icons/generated/shard-36.js +41 -41
  265. package/dist/icons/generated/shard-36.js.map +1 -1
  266. package/dist/icons/generated/shard-37.cjs +1 -1
  267. package/dist/icons/generated/shard-37.cjs.map +1 -1
  268. package/dist/icons/generated/shard-37.js +41 -41
  269. package/dist/icons/generated/shard-37.js.map +1 -1
  270. package/dist/icons/generated/shard-38.cjs +1 -1
  271. package/dist/icons/generated/shard-38.cjs.map +1 -1
  272. package/dist/icons/generated/shard-38.js +41 -41
  273. package/dist/icons/generated/shard-38.js.map +1 -1
  274. package/dist/icons/generated/shard-39.cjs +1 -1
  275. package/dist/icons/generated/shard-39.cjs.map +1 -1
  276. package/dist/icons/generated/shard-39.js +41 -41
  277. package/dist/icons/generated/shard-39.js.map +1 -1
  278. package/dist/icons/generated/shard-40.cjs +1 -1
  279. package/dist/icons/generated/shard-40.cjs.map +1 -1
  280. package/dist/icons/generated/shard-40.js +41 -41
  281. package/dist/icons/generated/shard-40.js.map +1 -1
  282. package/dist/icons/generated/shard-41.cjs +1 -1
  283. package/dist/icons/generated/shard-41.cjs.map +1 -1
  284. package/dist/icons/generated/shard-41.js +41 -41
  285. package/dist/icons/generated/shard-41.js.map +1 -1
  286. package/dist/icons/generated/shard-42.cjs +1 -1
  287. package/dist/icons/generated/shard-42.cjs.map +1 -1
  288. package/dist/icons/generated/shard-42.js +41 -41
  289. package/dist/icons/generated/shard-42.js.map +1 -1
  290. package/dist/icons/generated/shard-43.cjs +1 -1
  291. package/dist/icons/generated/shard-43.cjs.map +1 -1
  292. package/dist/icons/generated/shard-43.js +41 -41
  293. package/dist/icons/generated/shard-43.js.map +1 -1
  294. package/dist/icons/generated/shard-44.cjs +1 -1
  295. package/dist/icons/generated/shard-44.cjs.map +1 -1
  296. package/dist/icons/generated/shard-44.js +43 -10
  297. package/dist/icons/generated/shard-44.js.map +1 -1
  298. package/dist/icons/generated/shard-45.cjs +2 -0
  299. package/dist/icons/generated/shard-45.cjs.map +1 -0
  300. package/dist/icons/generated/shard-45.js +15 -0
  301. package/dist/icons/generated/shard-45.js.map +1 -0
  302. package/dist/icons/material-symbols.cjs +1 -1
  303. package/dist/icons/material-symbols.cjs.map +1 -1
  304. package/dist/icons/material-symbols.js +3 -3
  305. package/dist/icons/material-symbols.js.map +1 -1
  306. package/dist/icons.d.ts +4 -4
  307. package/dist/query/foreign-client-warning.cjs +1 -1
  308. package/dist/query/foreign-client-warning.cjs.map +1 -1
  309. package/dist/query/foreign-client-warning.js +1 -1
  310. package/dist/query/foreign-client-warning.js.map +1 -1
  311. package/dist/styles/Alert.css +1 -1
  312. package/dist/styles/Badge.css +1 -1
  313. package/dist/styles/BarList.css +3 -3
  314. package/dist/styles/BottomSheet.css +1 -1
  315. package/dist/styles/DataTable.css +1 -1
  316. package/dist/styles/Dropzone.css +1 -1
  317. package/dist/styles/ErrorText.css +1 -1
  318. package/dist/styles/Markdown.css +1 -1
  319. package/dist/styles/PasswordInput.css +1 -1
  320. package/dist/styles/SegmentedControl.css +1 -1
  321. package/dist/styles/Sidebar.css +2 -2
  322. package/dist/styles/StepperInput.css +1 -1
  323. package/dist/styles/Tag.css +1 -1
  324. package/dist/styles/Timeline.css +1 -1
  325. package/dist/styles/Toggle.css +1 -1
  326. package/dist/styles/ToggleGroup.css +1 -1
  327. package/dist/styles/advanced.css +2 -2
  328. package/dist/styles/core.css +4 -2
  329. package/dist/styles/data.css +6 -6
  330. package/dist/styles/feedback.css +3 -3
  331. package/dist/styles/forms.css +3 -3
  332. package/dist/styles/navigation.css +3 -3
  333. package/dist/styles/overlay.css +1 -1
  334. package/dist/styles/utility.css +1 -1
  335. package/dist/styles.css +1 -1
  336. package/dist/tempest-react-sdk.cjs +1 -1
  337. package/dist/tempest-react-sdk.d.ts +81 -7
  338. package/dist/tempest-react-sdk.js +347 -346
  339. package/dist/theme/create-theme.cjs +3 -3
  340. package/dist/theme/create-theme.cjs.map +1 -1
  341. package/dist/theme/create-theme.js +15 -14
  342. package/dist/theme/create-theme.js.map +1 -1
  343. package/dist/utils/dev-mode.cjs +1 -1
  344. package/dist/utils/dev-mode.cjs.map +1 -1
  345. package/dist/utils/dev-mode.js +7 -2
  346. package/dist/utils/dev-mode.js.map +1 -1
  347. package/dist/utils/json-frame.cjs +1 -1
  348. package/dist/utils/json-frame.cjs.map +1 -1
  349. package/dist/utils/json-frame.js +1 -1
  350. package/dist/utils/json-frame.js.map +1 -1
  351. package/dist/vision/core/providers.cjs +1 -1
  352. package/dist/vision/core/providers.cjs.map +1 -1
  353. package/dist/vision/core/providers.js +22 -3
  354. package/dist/vision/core/providers.js.map +1 -1
  355. package/dist/vision/core/session.cjs +1 -1
  356. package/dist/vision/core/session.cjs.map +1 -1
  357. package/dist/vision/core/session.js +22 -15
  358. package/dist/vision/core/session.js.map +1 -1
  359. package/dist/vision/fusion.cjs.map +1 -1
  360. package/dist/vision/fusion.js.map +1 -1
  361. package/dist/vision/index.cjs +1 -1
  362. package/dist/vision/index.cjs.map +1 -1
  363. package/dist/vision/index.js +17 -16
  364. package/dist/vision/index.js.map +1 -1
  365. package/dist/vision/normalization.cjs +2 -0
  366. package/dist/vision/normalization.cjs.map +1 -0
  367. package/dist/vision/normalization.js +49 -0
  368. package/dist/vision/normalization.js.map +1 -0
  369. package/dist/vision/results.cjs +1 -1
  370. package/dist/vision/results.cjs.map +1 -1
  371. package/dist/vision/results.js +8 -2
  372. package/dist/vision/results.js.map +1 -1
  373. package/dist/vision/tasks/classifier.cjs +1 -1
  374. package/dist/vision/tasks/classifier.cjs.map +1 -1
  375. package/dist/vision/tasks/classifier.js +36 -32
  376. package/dist/vision/tasks/classifier.js.map +1 -1
  377. package/dist/vision.cjs +1 -1
  378. package/dist/vision.d.ts +218 -13
  379. package/dist/vision.js +19 -18
  380. package/dist/vite/tempest-pwa-manifest.cjs +1 -1
  381. package/dist/vite/tempest-pwa-manifest.cjs.map +1 -1
  382. package/dist/vite/tempest-pwa-manifest.js +1 -1
  383. package/dist/vite/tempest-pwa-manifest.js.map +1 -1
  384. package/dist/webrtc/peer-link.cjs +1 -1
  385. package/dist/webrtc/peer-link.cjs.map +1 -1
  386. package/dist/webrtc/peer-link.js +1 -1
  387. package/dist/webrtc/peer-link.js.map +1 -1
  388. package/dist/webrtc/peer-mesh.cjs +1 -1
  389. package/dist/webrtc/peer-mesh.cjs.map +1 -1
  390. package/dist/webrtc/peer-mesh.js +1 -1
  391. package/dist/webrtc/peer-mesh.js.map +1 -1
  392. package/dist/ws/create-web-socket.cjs +1 -1
  393. package/dist/ws/create-web-socket.cjs.map +1 -1
  394. package/dist/ws/create-web-socket.js +1 -1
  395. package/dist/ws/create-web-socket.js.map +1 -1
  396. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ImageCropper.cjs","names":[],"sources":["../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — pointer drag, wheel\n * zoom, aspect clamping and canvas export share one piece of geometry state, and the\n * props are the two halves of that: the frame (aspect, shape, maxZoom, label) and\n * the export (maxSize, outputType, outputQuality, onCropChange, ref). Threading the\n * geometry through props would duplicate the clamp maths.\n */\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport {\n clampOffset,\n computeCropRect,\n coverScale,\n type Offset,\n outputSize,\n type Size,\n} from \"./crop-geometry\";\nimport styles from \"./ImageCropper.module.css\";\n\n/** Imperative handle for exporting the current crop. */\nexport interface ImageCropperHandle {\n /**\n * Render the current crop and resolve with it.\n *\n * Resolves `null` when the image has not loaded yet or the browser refuses to\n * encode — never throws, so a submit handler does not need a try/catch.\n */\n crop: () => Promise<Blob | null>;\n /** Recentre at zoom 1. */\n reset: () => void;\n}\n\nexport interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The image to crop: a `File`/`Blob` from an input, or a URL. */\n src: File | Blob | string;\n /** Crop aspect ratio as `width / height`. Default `1` (square). */\n aspect?: number;\n /** Maximum zoom over the cover scale. Default `4`. */\n maxZoom?: number;\n /**\n * Cap on the longest edge of the exported image, in px.\n *\n * Without it the export keeps the source resolution, which is right for a\n * document scan and wasteful for an avatar.\n */\n maxSize?: number;\n /** Output MIME type. Default `\"image/png\"`. */\n outputType?: string;\n /** Output quality for lossy types, `0`–`1`. Default `0.92`. */\n outputQuality?: number;\n /** Overlay shape. `\"circle\"` for an avatar, `\"rect\"` for a document. Default `\"rect\"`. */\n shape?: \"rect\" | \"circle\";\n /** Called whenever the crop changes, e.g. to enable a submit button. */\n onCropChange?: (state: { zoom: number; offset: Offset }) => void;\n /** Accessible name for the crop area. */\n label?: string;\n ref?: React.Ref<ImageCropperHandle>;\n}\n\n/** Pixels moved per arrow-key press. */\nconst KEY_STEP = 12;\n\n/** Zoom added or removed per `+`/`-` press, and per wheel notch. */\nconst ZOOM_STEP = 0.15;\n\n/**\n * Crop an image to a fixed aspect ratio.\n *\n * The frame stays put and the image pans and zooms behind it — the model an avatar\n * or document-photo flow wants, where the output shape is decided by the app and\n * the user only chooses what lands inside it. (A free-form draggable rectangle is a\n * different component; this one cannot produce an off-ratio crop by construction.)\n *\n * The export reads the *natural* pixels through a canvas, so a 4000 px photo is not\n * silently downsampled to whatever the on-screen preview measured. The image is\n * also always clamped to cover the frame, so an export can never contain the empty\n * bands you get from panning past an edge.\n *\n * Works by pointer, wheel and keyboard: arrows pan, `+`/`-` zoom, `0` resets.\n *\n * @example\n * const cropper = useRef<ImageCropperHandle>(null);\n *\n * <ImageCropper ref={cropper} src={file} aspect={1} shape=\"circle\" maxSize={512} />\n * <Button onClick={async () => upload(await cropper.current?.crop())}>Salvar</Button>\n */\nexport function ImageCropper({\n src,\n aspect = 1,\n maxZoom = 4,\n maxSize,\n outputType = \"image/png\",\n outputQuality = 0.92,\n shape = \"rect\",\n onCropChange,\n label = \"Área de recorte\",\n className,\n ref,\n ...rest\n}: ImageCropperProps) {\n /**\n * Id for the shortcut hint.\n *\n * Generated rather than derived from `label`: a label with spaces would produce\n * an id with spaces, and `aria-describedby` splits on whitespace — so the\n * description would silently never associate with the frame.\n */\n const hintId = `${useId()}-hint`;\n\n const frameRef = useRef<HTMLDivElement>(null);\n const imageRef = useRef<HTMLImageElement | null>(null);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n from: Offset;\n } | null>(null);\n\n const [url, setUrl] = useState<string | null>(null);\n const [natural, setNatural] = useState<Size | null>(null);\n const [frame, setFrame] = useState<Size>({ width: 0, height: 0 });\n const [zoom, setZoom] = useState(1);\n const [offset, setOffset] = useState<Offset>({ x: 0, y: 0 });\n\n /**\n * Resolve `src` to a displayable URL.\n *\n * A `File`/`Blob` needs `createObjectURL`, and the URL must be revoked when the\n * source changes or the component unmounts — otherwise every re-pick of a photo\n * leaks the previous one for the lifetime of the document.\n */\n useEffect(() => {\n if (typeof src === \"string\") {\n setUrl(src);\n return;\n }\n const objectUrl = URL.createObjectURL(src);\n setUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [src]);\n\n // A new source invalidates the previous framing.\n useEffect(() => {\n setNatural(null);\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n }, [url]);\n\n /** Track the frame's rendered size — the crop math is all relative to it. */\n useEffect(() => {\n const element = frameRef.current;\n if (!element) return;\n const measure = () =>\n setFrame({ width: element.clientWidth, height: element.clientHeight });\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const scale = natural ? coverScale(natural, frame) * zoom : 0;\n\n /**\n * On-screen image size.\n *\n * Memoized because the pan callback depends on it: a fresh object every render\n * would rebuild that callback every render, and the pointer handlers close over\n * it during a drag.\n */\n const displayed = useMemo<Size>(\n () =>\n natural\n ? { width: natural.width * scale, height: natural.height * scale }\n : { width: 0, height: 0 },\n [natural, scale],\n );\n\n /** Apply a pan, clamped so the frame stays covered. */\n const pan = useCallback(\n (next: Offset) => {\n setOffset((current) => {\n const clamped = clampOffset(next, displayed, frame);\n if (clamped.x === current.x && clamped.y === current.y) return current;\n onCropChange?.({ zoom, offset: clamped });\n return clamped;\n });\n },\n [displayed, frame, onCropChange, zoom],\n );\n\n /**\n * Apply a zoom, then re-clamp the offset.\n *\n * Re-clamping is not optional: zooming *out* shrinks the image, so an offset\n * that was legal a moment ago can now expose background.\n */\n const applyZoom = useCallback(\n (next: number) => {\n const clampedZoom = Math.min(maxZoom, Math.max(1, next));\n setZoom(clampedZoom);\n if (!natural) return;\n const nextScale = coverScale(natural, frame) * clampedZoom;\n const nextDisplayed = {\n width: natural.width * nextScale,\n height: natural.height * nextScale,\n };\n setOffset((current) => {\n const clamped = clampOffset(current, nextDisplayed, frame);\n onCropChange?.({ zoom: clampedZoom, offset: clamped });\n return clamped;\n });\n },\n [frame, maxZoom, natural, onCropChange],\n );\n\n const reset = useCallback(() => {\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n onCropChange?.({ zoom: 1, offset: { x: 0, y: 0 } });\n }, [onCropChange]);\n\n /**\n * Draw the current crop and encode it.\n *\n * Returns `null` rather than throwing on the paths a caller cannot do anything\n * about: no image yet, no 2D context, or an encoder that declined.\n */\n const crop = useCallback(async (): Promise<Blob | null> => {\n const image = imageRef.current;\n if (!image || !natural) return null;\n\n const rect = computeCropRect({ image: natural, frame, zoom, offset });\n if (rect.sWidth <= 0 || rect.sHeight <= 0) return null;\n\n const out = outputSize(rect, maxSize);\n const canvas = document.createElement(\"canvas\");\n canvas.width = out.width;\n canvas.height = out.height;\n const context = canvas.getContext(\"2d\");\n if (!context) return null;\n\n context.drawImage(\n image,\n rect.sx,\n rect.sy,\n rect.sWidth,\n rect.sHeight,\n 0,\n 0,\n out.width,\n out.height,\n );\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob), outputType, outputQuality);\n });\n }, [frame, maxSize, natural, offset, outputQuality, outputType, zoom]);\n\n useImperativeHandle(ref, () => ({ crop, reset }), [crop, reset]);\n\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (!natural) return;\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n from: offset,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n };\n\n const onPointerMove = (event: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n pan({\n x: drag.from.x + (event.clientX - drag.startX),\n y: drag.from.y + (event.clientY - drag.startY),\n });\n };\n\n const endDrag = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n const step = event.shiftKey ? KEY_STEP * 4 : KEY_STEP;\n const moves: Record<string, Offset> = {\n ArrowLeft: { x: -step, y: 0 },\n ArrowRight: { x: step, y: 0 },\n ArrowUp: { x: 0, y: -step },\n ArrowDown: { x: 0, y: step },\n };\n const move = moves[event.key];\n if (move) {\n event.preventDefault();\n pan({ x: offset.x + move.x, y: offset.y + move.y });\n return;\n }\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n applyZoom(zoom + ZOOM_STEP);\n } else if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n applyZoom(zoom - ZOOM_STEP);\n } else if (event.key === \"0\") {\n event.preventDefault();\n reset();\n }\n };\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n <div\n ref={frameRef}\n className={cn(styles.frame, shape === \"circle\" && styles.circle)}\n style={{ aspectRatio: String(aspect) }}\n role=\"group\"\n aria-label={label}\n aria-describedby={hintId}\n tabIndex={0}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onKeyDown}\n onWheel={(event) => {\n event.preventDefault();\n applyZoom(zoom + (event.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP));\n }}\n >\n {url && (\n <img\n ref={imageRef}\n src={url}\n alt=\"\"\n draggable={false}\n className={styles.image}\n style={{\n width: displayed.width || undefined,\n height: displayed.height || undefined,\n transform: `translate(${offset.x}px, ${offset.y}px)`,\n }}\n onLoad={(event) => {\n const element = event.currentTarget;\n // A decode can succeed and still report no intrinsic size —\n // an SVG without a viewBox is the common case. Accepting\n // that would enable the controls over an image the crop\n // maths can do nothing with.\n if (element.naturalWidth > 0 && element.naturalHeight > 0) {\n setNatural({\n width: element.naturalWidth,\n height: element.naturalHeight,\n });\n }\n }}\n />\n )}\n </div>\n\n <div className={styles.controls}>\n <input\n type=\"range\"\n className={styles.zoom}\n min={1}\n max={maxZoom}\n step={0.01}\n value={zoom}\n onChange={(event) => applyZoom(Number(event.target.value))}\n aria-label=\"Zoom\"\n disabled={!natural}\n />\n <button type=\"button\" className={styles.reset} onClick={reset} disabled={!natural}>\n Centralizar\n </button>\n </div>\n\n <p id={hintId} className={styles.hint}>\n Arraste para reposicionar. Setas movem, <kbd>+</kbd> e <kbd>−</kbd> dão zoom,{\" \"}\n <kbd>0</kbd> centraliza.\n </p>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ImageCropper.cjs","names":[],"sources":["../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — pointer drag, wheel\n * zoom, aspect clamping and canvas export share one piece of geometry state, and the\n * props are the two halves of that: the frame (aspect, shape, maxZoom, label) and\n * the export (maxSize, outputType, outputQuality, onCropChange, ref). Threading the\n * geometry through props would duplicate the clamp maths.\n */\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport {\n clampOffset,\n computeCropRect,\n coverScale,\n type Offset,\n outputSize,\n type Size,\n} from \"./crop-geometry\";\nimport styles from \"./ImageCropper.module.css\";\n\n/** Imperative handle for exporting the current crop. */\nexport interface ImageCropperHandle {\n /**\n * Render the current crop and resolve with it.\n *\n * Resolves `null` when the image has not loaded yet or the browser refuses to\n * encode — never throws, so a submit handler does not need a try/catch.\n */\n crop: () => Promise<Blob | null>;\n /** Recentre at zoom 1. */\n reset: () => void;\n}\n\nexport interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The image to crop: a `File`/`Blob` from an input, or a URL. */\n src: File | Blob | string;\n /** Crop aspect ratio as `width / height`. Default `1` (square). */\n aspect?: number;\n /** Maximum zoom over the cover scale. Default `4`. */\n maxZoom?: number;\n /**\n * Cap on the longest edge of the exported image, in px.\n *\n * Without it the export keeps the source resolution, which is right for a\n * document scan and wasteful for an avatar.\n */\n maxSize?: number;\n /** Output MIME type. Default `\"image/png\"`. */\n outputType?: string;\n /** Output quality for lossy types, `0`–`1`. Default `0.92`. */\n outputQuality?: number;\n /** Overlay shape. `\"circle\"` for an avatar, `\"rect\"` for a document. Default `\"rect\"`. */\n shape?: \"rect\" | \"circle\";\n /** Called whenever the crop changes, e.g. to enable a submit button. */\n onCropChange?: (state: { zoom: number; offset: Offset }) => void;\n /** Accessible name for the crop area. */\n label?: string;\n ref?: React.Ref<ImageCropperHandle>;\n}\n\n/** Pixels moved per arrow-key press. */\nconst KEY_STEP = 12;\n\n/** Zoom added or removed per `+`/`-` press, and per wheel notch. */\nconst ZOOM_STEP = 0.15;\n\n/**\n * Crop an image to a fixed aspect ratio.\n *\n * The frame stays put and the image pans and zooms behind it — the model an avatar\n * or document-photo flow wants, where the output shape is decided by the app and\n * the user only chooses what lands inside it. (A free-form draggable rectangle is a\n * different component; this one cannot produce an off-ratio crop by construction.)\n *\n * The export reads the *natural* pixels through a canvas, so a 4000 px photo is not\n * silently downsampled to whatever the on-screen preview measured. The image is\n * also always clamped to cover the frame, so an export can never contain the empty\n * bands you get from panning past an edge.\n *\n * Works by pointer, wheel and keyboard: arrows pan, `+`/`-` zoom, `0` resets.\n *\n * @example\n * const cropper = useRef<ImageCropperHandle>(null);\n *\n * <ImageCropper ref={cropper} src={file} aspect={1} shape=\"circle\" maxSize={512} />\n * <Button onClick={async () => upload(await cropper.current?.crop())}>Salvar</Button>\n */\nexport function ImageCropper({\n src,\n aspect = 1,\n maxZoom = 4,\n maxSize,\n outputType = \"image/png\",\n outputQuality = 0.92,\n shape = \"rect\",\n onCropChange,\n label = \"Área de recorte\",\n className,\n ref,\n ...rest\n}: ImageCropperProps) {\n /**\n * Id for the shortcut hint.\n *\n * Generated rather than derived from `label`: a label with spaces would produce\n * an id with spaces, and `aria-describedby` splits on whitespace — so the\n * description would silently never associate with the frame.\n */\n const hintId = `${useId()}-hint`;\n\n const frameRef = useRef<HTMLDivElement>(null);\n const imageRef = useRef<HTMLImageElement | null>(null);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n from: Offset;\n } | null>(null);\n\n const [url, setUrl] = useState<string | null>(null);\n const [natural, setNatural] = useState<Size | null>(null);\n const [frame, setFrame] = useState<Size>({ width: 0, height: 0 });\n const [zoom, setZoom] = useState(1);\n const [offset, setOffset] = useState<Offset>({ x: 0, y: 0 });\n\n /**\n * Resolve `src` to a displayable URL.\n *\n * A `File`/`Blob` needs `createObjectURL`, and the URL must be revoked when the\n * source changes or the component unmounts — otherwise every re-pick of a photo\n * leaks the previous one for the lifetime of the document.\n */\n useEffect(() => {\n if (typeof src === \"string\") {\n setUrl(src);\n return;\n }\n const objectUrl = URL.createObjectURL(src);\n setUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [src]);\n\n // A new source invalidates the previous framing.\n useEffect(() => {\n setNatural(null);\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n }, [url]);\n\n /** Track the frame's rendered size — the crop math is all relative to it. */\n useEffect(() => {\n const element = frameRef.current;\n if (!element) return;\n const measure = () =>\n setFrame({ width: element.clientWidth, height: element.clientHeight });\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const scale = natural ? coverScale(natural, frame) * zoom : 0;\n\n /**\n * On-screen image size.\n *\n * Memoized because the pan callback depends on it: a fresh object every render\n * would rebuild that callback every render, and the pointer handlers close over\n * it during a drag.\n */\n const displayed = useMemo<Size>(\n () =>\n natural\n ? { width: natural.width * scale, height: natural.height * scale }\n : { width: 0, height: 0 },\n [natural, scale],\n );\n\n /** Apply a pan, clamped so the frame stays covered. */\n const pan = useCallback(\n (next: Offset) => {\n setOffset((current) => {\n const clamped = clampOffset(next, displayed, frame);\n if (clamped.x === current.x && clamped.y === current.y) return current;\n onCropChange?.({ zoom, offset: clamped });\n return clamped;\n });\n },\n [displayed, frame, onCropChange, zoom],\n );\n\n /**\n * Apply a zoom, then re-clamp the offset.\n *\n * Re-clamping is not optional: zooming *out* shrinks the image, so an offset\n * that was legal a moment ago can now expose background.\n */\n const applyZoom = useCallback(\n (next: number) => {\n const clampedZoom = Math.min(maxZoom, Math.max(1, next));\n setZoom(clampedZoom);\n if (!natural) return;\n const nextScale = coverScale(natural, frame) * clampedZoom;\n const nextDisplayed = {\n width: natural.width * nextScale,\n height: natural.height * nextScale,\n };\n setOffset((current) => {\n const clamped = clampOffset(current, nextDisplayed, frame);\n onCropChange?.({ zoom: clampedZoom, offset: clamped });\n return clamped;\n });\n },\n [frame, maxZoom, natural, onCropChange],\n );\n\n const reset = useCallback(() => {\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n onCropChange?.({ zoom: 1, offset: { x: 0, y: 0 } });\n }, [onCropChange]);\n\n /**\n * Draw the current crop and encode it.\n *\n * Returns `null` rather than throwing on the paths a caller cannot do anything\n * about: no image yet, no 2D context, or an encoder that declined.\n */\n const crop = useCallback(async (): Promise<Blob | null> => {\n const image = imageRef.current;\n if (!image || !natural) return null;\n\n const rect = computeCropRect({ image: natural, frame, zoom, offset });\n if (rect.sWidth <= 0 || rect.sHeight <= 0) return null;\n\n const out = outputSize(rect, maxSize);\n const canvas = document.createElement(\"canvas\");\n canvas.width = out.width;\n canvas.height = out.height;\n const context = canvas.getContext(\"2d\");\n if (!context) return null;\n\n context.drawImage(\n image,\n rect.sx,\n rect.sy,\n rect.sWidth,\n rect.sHeight,\n 0,\n 0,\n out.width,\n out.height,\n );\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob), outputType, outputQuality);\n });\n }, [frame, maxSize, natural, offset, outputQuality, outputType, zoom]);\n\n useImperativeHandle(ref, () => ({ crop, reset }), [crop, reset]);\n\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (!natural) return;\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n from: offset,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n };\n\n const onPointerMove = (event: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n pan({\n x: drag.from.x + (event.clientX - drag.startX),\n y: drag.from.y + (event.clientY - drag.startY),\n });\n };\n\n const endDrag = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n const step = event.shiftKey ? KEY_STEP * 4 : KEY_STEP;\n const moves: Record<string, Offset> = {\n ArrowLeft: { x: -step, y: 0 },\n ArrowRight: { x: step, y: 0 },\n ArrowUp: { x: 0, y: -step },\n ArrowDown: { x: 0, y: step },\n };\n const move = moves[event.key];\n if (move) {\n event.preventDefault();\n pan({ x: offset.x + move.x, y: offset.y + move.y });\n return;\n }\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n applyZoom(zoom + ZOOM_STEP);\n } else if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n applyZoom(zoom - ZOOM_STEP);\n } else if (event.key === \"0\") {\n event.preventDefault();\n reset();\n }\n };\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n <div\n ref={frameRef}\n className={cn(styles.frame, shape === \"circle\" && styles.circle)}\n style={{ aspectRatio: String(aspect) }}\n role=\"group\"\n aria-label={label}\n aria-describedby={hintId}\n tabIndex={0}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onKeyDown}\n onWheel={(event) => {\n event.preventDefault();\n applyZoom(zoom + (event.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP));\n }}\n >\n {url && (\n <img\n ref={imageRef}\n src={url}\n alt=\"\"\n draggable={false}\n className={styles.image}\n style={{\n width: displayed.width || undefined,\n height: displayed.height || undefined,\n transform: `translate(${offset.x}px, ${offset.y}px)`,\n }}\n onLoad={(event) => {\n const element = event.currentTarget;\n // A decode can succeed and still report no intrinsic size —\n // an SVG without a viewBox is the common case. Accepting\n // that would enable the controls over an image the crop\n // maths can do nothing with.\n if (element.naturalWidth > 0 && element.naturalHeight > 0) {\n setNatural({\n width: element.naturalWidth,\n height: element.naturalHeight,\n });\n }\n }}\n />\n )}\n </div>\n\n <div className={styles.controls}>\n <input\n type=\"range\"\n className={styles.zoom}\n min={1}\n max={maxZoom}\n step={0.01}\n value={zoom}\n onChange={(event) => applyZoom(Number(event.target.value))}\n aria-label=\"Zoom\"\n disabled={!natural}\n />\n <button type=\"button\" className={styles.reset} onClick={reset} disabled={!natural}>\n Centralizar\n </button>\n </div>\n\n <p id={hintId} className={styles.hint}>\n Arraste para reposicionar. Setas movem, <kbd>+</kbd> e <kbd>−</kbd> dão zoom,{\" \"}\n <kbd>0</kbd> centraliza.\n </p>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -123,7 +123,7 @@ function _({ src: _, aspect: v = 1, maxZoom: y = 4, maxSize: b, outputType: x =
123
123
  }, e.currentTarget.setPointerCapture?.(e.pointerId));
124
124
  }, X = (e) => {
125
125
  let t = M.current;
126
- !t || t.pointerId !== e.pointerId || G({
126
+ t && t.pointerId === e.pointerId && G({
127
127
  x: t.from.x + (e.clientX - t.startX),
128
128
  y: t.from.y + (e.clientY - t.startY)
129
129
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ImageCropper.js","names":[],"sources":["../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — pointer drag, wheel\n * zoom, aspect clamping and canvas export share one piece of geometry state, and the\n * props are the two halves of that: the frame (aspect, shape, maxZoom, label) and\n * the export (maxSize, outputType, outputQuality, onCropChange, ref). Threading the\n * geometry through props would duplicate the clamp maths.\n */\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport {\n clampOffset,\n computeCropRect,\n coverScale,\n type Offset,\n outputSize,\n type Size,\n} from \"./crop-geometry\";\nimport styles from \"./ImageCropper.module.css\";\n\n/** Imperative handle for exporting the current crop. */\nexport interface ImageCropperHandle {\n /**\n * Render the current crop and resolve with it.\n *\n * Resolves `null` when the image has not loaded yet or the browser refuses to\n * encode — never throws, so a submit handler does not need a try/catch.\n */\n crop: () => Promise<Blob | null>;\n /** Recentre at zoom 1. */\n reset: () => void;\n}\n\nexport interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The image to crop: a `File`/`Blob` from an input, or a URL. */\n src: File | Blob | string;\n /** Crop aspect ratio as `width / height`. Default `1` (square). */\n aspect?: number;\n /** Maximum zoom over the cover scale. Default `4`. */\n maxZoom?: number;\n /**\n * Cap on the longest edge of the exported image, in px.\n *\n * Without it the export keeps the source resolution, which is right for a\n * document scan and wasteful for an avatar.\n */\n maxSize?: number;\n /** Output MIME type. Default `\"image/png\"`. */\n outputType?: string;\n /** Output quality for lossy types, `0`–`1`. Default `0.92`. */\n outputQuality?: number;\n /** Overlay shape. `\"circle\"` for an avatar, `\"rect\"` for a document. Default `\"rect\"`. */\n shape?: \"rect\" | \"circle\";\n /** Called whenever the crop changes, e.g. to enable a submit button. */\n onCropChange?: (state: { zoom: number; offset: Offset }) => void;\n /** Accessible name for the crop area. */\n label?: string;\n ref?: React.Ref<ImageCropperHandle>;\n}\n\n/** Pixels moved per arrow-key press. */\nconst KEY_STEP = 12;\n\n/** Zoom added or removed per `+`/`-` press, and per wheel notch. */\nconst ZOOM_STEP = 0.15;\n\n/**\n * Crop an image to a fixed aspect ratio.\n *\n * The frame stays put and the image pans and zooms behind it — the model an avatar\n * or document-photo flow wants, where the output shape is decided by the app and\n * the user only chooses what lands inside it. (A free-form draggable rectangle is a\n * different component; this one cannot produce an off-ratio crop by construction.)\n *\n * The export reads the *natural* pixels through a canvas, so a 4000 px photo is not\n * silently downsampled to whatever the on-screen preview measured. The image is\n * also always clamped to cover the frame, so an export can never contain the empty\n * bands you get from panning past an edge.\n *\n * Works by pointer, wheel and keyboard: arrows pan, `+`/`-` zoom, `0` resets.\n *\n * @example\n * const cropper = useRef<ImageCropperHandle>(null);\n *\n * <ImageCropper ref={cropper} src={file} aspect={1} shape=\"circle\" maxSize={512} />\n * <Button onClick={async () => upload(await cropper.current?.crop())}>Salvar</Button>\n */\nexport function ImageCropper({\n src,\n aspect = 1,\n maxZoom = 4,\n maxSize,\n outputType = \"image/png\",\n outputQuality = 0.92,\n shape = \"rect\",\n onCropChange,\n label = \"Área de recorte\",\n className,\n ref,\n ...rest\n}: ImageCropperProps) {\n /**\n * Id for the shortcut hint.\n *\n * Generated rather than derived from `label`: a label with spaces would produce\n * an id with spaces, and `aria-describedby` splits on whitespace — so the\n * description would silently never associate with the frame.\n */\n const hintId = `${useId()}-hint`;\n\n const frameRef = useRef<HTMLDivElement>(null);\n const imageRef = useRef<HTMLImageElement | null>(null);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n from: Offset;\n } | null>(null);\n\n const [url, setUrl] = useState<string | null>(null);\n const [natural, setNatural] = useState<Size | null>(null);\n const [frame, setFrame] = useState<Size>({ width: 0, height: 0 });\n const [zoom, setZoom] = useState(1);\n const [offset, setOffset] = useState<Offset>({ x: 0, y: 0 });\n\n /**\n * Resolve `src` to a displayable URL.\n *\n * A `File`/`Blob` needs `createObjectURL`, and the URL must be revoked when the\n * source changes or the component unmounts — otherwise every re-pick of a photo\n * leaks the previous one for the lifetime of the document.\n */\n useEffect(() => {\n if (typeof src === \"string\") {\n setUrl(src);\n return;\n }\n const objectUrl = URL.createObjectURL(src);\n setUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [src]);\n\n // A new source invalidates the previous framing.\n useEffect(() => {\n setNatural(null);\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n }, [url]);\n\n /** Track the frame's rendered size — the crop math is all relative to it. */\n useEffect(() => {\n const element = frameRef.current;\n if (!element) return;\n const measure = () =>\n setFrame({ width: element.clientWidth, height: element.clientHeight });\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const scale = natural ? coverScale(natural, frame) * zoom : 0;\n\n /**\n * On-screen image size.\n *\n * Memoized because the pan callback depends on it: a fresh object every render\n * would rebuild that callback every render, and the pointer handlers close over\n * it during a drag.\n */\n const displayed = useMemo<Size>(\n () =>\n natural\n ? { width: natural.width * scale, height: natural.height * scale }\n : { width: 0, height: 0 },\n [natural, scale],\n );\n\n /** Apply a pan, clamped so the frame stays covered. */\n const pan = useCallback(\n (next: Offset) => {\n setOffset((current) => {\n const clamped = clampOffset(next, displayed, frame);\n if (clamped.x === current.x && clamped.y === current.y) return current;\n onCropChange?.({ zoom, offset: clamped });\n return clamped;\n });\n },\n [displayed, frame, onCropChange, zoom],\n );\n\n /**\n * Apply a zoom, then re-clamp the offset.\n *\n * Re-clamping is not optional: zooming *out* shrinks the image, so an offset\n * that was legal a moment ago can now expose background.\n */\n const applyZoom = useCallback(\n (next: number) => {\n const clampedZoom = Math.min(maxZoom, Math.max(1, next));\n setZoom(clampedZoom);\n if (!natural) return;\n const nextScale = coverScale(natural, frame) * clampedZoom;\n const nextDisplayed = {\n width: natural.width * nextScale,\n height: natural.height * nextScale,\n };\n setOffset((current) => {\n const clamped = clampOffset(current, nextDisplayed, frame);\n onCropChange?.({ zoom: clampedZoom, offset: clamped });\n return clamped;\n });\n },\n [frame, maxZoom, natural, onCropChange],\n );\n\n const reset = useCallback(() => {\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n onCropChange?.({ zoom: 1, offset: { x: 0, y: 0 } });\n }, [onCropChange]);\n\n /**\n * Draw the current crop and encode it.\n *\n * Returns `null` rather than throwing on the paths a caller cannot do anything\n * about: no image yet, no 2D context, or an encoder that declined.\n */\n const crop = useCallback(async (): Promise<Blob | null> => {\n const image = imageRef.current;\n if (!image || !natural) return null;\n\n const rect = computeCropRect({ image: natural, frame, zoom, offset });\n if (rect.sWidth <= 0 || rect.sHeight <= 0) return null;\n\n const out = outputSize(rect, maxSize);\n const canvas = document.createElement(\"canvas\");\n canvas.width = out.width;\n canvas.height = out.height;\n const context = canvas.getContext(\"2d\");\n if (!context) return null;\n\n context.drawImage(\n image,\n rect.sx,\n rect.sy,\n rect.sWidth,\n rect.sHeight,\n 0,\n 0,\n out.width,\n out.height,\n );\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob), outputType, outputQuality);\n });\n }, [frame, maxSize, natural, offset, outputQuality, outputType, zoom]);\n\n useImperativeHandle(ref, () => ({ crop, reset }), [crop, reset]);\n\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (!natural) return;\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n from: offset,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n };\n\n const onPointerMove = (event: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n pan({\n x: drag.from.x + (event.clientX - drag.startX),\n y: drag.from.y + (event.clientY - drag.startY),\n });\n };\n\n const endDrag = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n const step = event.shiftKey ? KEY_STEP * 4 : KEY_STEP;\n const moves: Record<string, Offset> = {\n ArrowLeft: { x: -step, y: 0 },\n ArrowRight: { x: step, y: 0 },\n ArrowUp: { x: 0, y: -step },\n ArrowDown: { x: 0, y: step },\n };\n const move = moves[event.key];\n if (move) {\n event.preventDefault();\n pan({ x: offset.x + move.x, y: offset.y + move.y });\n return;\n }\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n applyZoom(zoom + ZOOM_STEP);\n } else if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n applyZoom(zoom - ZOOM_STEP);\n } else if (event.key === \"0\") {\n event.preventDefault();\n reset();\n }\n };\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n <div\n ref={frameRef}\n className={cn(styles.frame, shape === \"circle\" && styles.circle)}\n style={{ aspectRatio: String(aspect) }}\n role=\"group\"\n aria-label={label}\n aria-describedby={hintId}\n tabIndex={0}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onKeyDown}\n onWheel={(event) => {\n event.preventDefault();\n applyZoom(zoom + (event.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP));\n }}\n >\n {url && (\n <img\n ref={imageRef}\n src={url}\n alt=\"\"\n draggable={false}\n className={styles.image}\n style={{\n width: displayed.width || undefined,\n height: displayed.height || undefined,\n transform: `translate(${offset.x}px, ${offset.y}px)`,\n }}\n onLoad={(event) => {\n const element = event.currentTarget;\n // A decode can succeed and still report no intrinsic size —\n // an SVG without a viewBox is the common case. Accepting\n // that would enable the controls over an image the crop\n // maths can do nothing with.\n if (element.naturalWidth > 0 && element.naturalHeight > 0) {\n setNatural({\n width: element.naturalWidth,\n height: element.naturalHeight,\n });\n }\n }}\n />\n )}\n </div>\n\n <div className={styles.controls}>\n <input\n type=\"range\"\n className={styles.zoom}\n min={1}\n max={maxZoom}\n step={0.01}\n value={zoom}\n onChange={(event) => applyZoom(Number(event.target.value))}\n aria-label=\"Zoom\"\n disabled={!natural}\n />\n <button type=\"button\" className={styles.reset} onClick={reset} disabled={!natural}>\n Centralizar\n </button>\n </div>\n\n <p id={hintId} className={styles.hint}>\n Arraste para reposicionar. Setas movem, <kbd>+</kbd> e <kbd>−</kbd> dão zoom,{\" \"}\n <kbd>0</kbd> centraliza.\n </p>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ImageCropper.js","names":[],"sources":["../../../src/components/ImageCropper/ImageCropper.tsx"],"sourcesContent":["/**\n * @tempest-limits file-lines, props-count, function-lines — pointer drag, wheel\n * zoom, aspect clamping and canvas export share one piece of geometry state, and the\n * props are the two halves of that: the frame (aspect, shape, maxZoom, label) and\n * the export (maxSize, outputType, outputQuality, onCropChange, ref). Threading the\n * geometry through props would duplicate the clamp maths.\n */\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type PointerEvent as ReactPointerEvent,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport {\n clampOffset,\n computeCropRect,\n coverScale,\n type Offset,\n outputSize,\n type Size,\n} from \"./crop-geometry\";\nimport styles from \"./ImageCropper.module.css\";\n\n/** Imperative handle for exporting the current crop. */\nexport interface ImageCropperHandle {\n /**\n * Render the current crop and resolve with it.\n *\n * Resolves `null` when the image has not loaded yet or the browser refuses to\n * encode — never throws, so a submit handler does not need a try/catch.\n */\n crop: () => Promise<Blob | null>;\n /** Recentre at zoom 1. */\n reset: () => void;\n}\n\nexport interface ImageCropperProps extends Omit<HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** The image to crop: a `File`/`Blob` from an input, or a URL. */\n src: File | Blob | string;\n /** Crop aspect ratio as `width / height`. Default `1` (square). */\n aspect?: number;\n /** Maximum zoom over the cover scale. Default `4`. */\n maxZoom?: number;\n /**\n * Cap on the longest edge of the exported image, in px.\n *\n * Without it the export keeps the source resolution, which is right for a\n * document scan and wasteful for an avatar.\n */\n maxSize?: number;\n /** Output MIME type. Default `\"image/png\"`. */\n outputType?: string;\n /** Output quality for lossy types, `0`–`1`. Default `0.92`. */\n outputQuality?: number;\n /** Overlay shape. `\"circle\"` for an avatar, `\"rect\"` for a document. Default `\"rect\"`. */\n shape?: \"rect\" | \"circle\";\n /** Called whenever the crop changes, e.g. to enable a submit button. */\n onCropChange?: (state: { zoom: number; offset: Offset }) => void;\n /** Accessible name for the crop area. */\n label?: string;\n ref?: React.Ref<ImageCropperHandle>;\n}\n\n/** Pixels moved per arrow-key press. */\nconst KEY_STEP = 12;\n\n/** Zoom added or removed per `+`/`-` press, and per wheel notch. */\nconst ZOOM_STEP = 0.15;\n\n/**\n * Crop an image to a fixed aspect ratio.\n *\n * The frame stays put and the image pans and zooms behind it — the model an avatar\n * or document-photo flow wants, where the output shape is decided by the app and\n * the user only chooses what lands inside it. (A free-form draggable rectangle is a\n * different component; this one cannot produce an off-ratio crop by construction.)\n *\n * The export reads the *natural* pixels through a canvas, so a 4000 px photo is not\n * silently downsampled to whatever the on-screen preview measured. The image is\n * also always clamped to cover the frame, so an export can never contain the empty\n * bands you get from panning past an edge.\n *\n * Works by pointer, wheel and keyboard: arrows pan, `+`/`-` zoom, `0` resets.\n *\n * @example\n * const cropper = useRef<ImageCropperHandle>(null);\n *\n * <ImageCropper ref={cropper} src={file} aspect={1} shape=\"circle\" maxSize={512} />\n * <Button onClick={async () => upload(await cropper.current?.crop())}>Salvar</Button>\n */\nexport function ImageCropper({\n src,\n aspect = 1,\n maxZoom = 4,\n maxSize,\n outputType = \"image/png\",\n outputQuality = 0.92,\n shape = \"rect\",\n onCropChange,\n label = \"Área de recorte\",\n className,\n ref,\n ...rest\n}: ImageCropperProps) {\n /**\n * Id for the shortcut hint.\n *\n * Generated rather than derived from `label`: a label with spaces would produce\n * an id with spaces, and `aria-describedby` splits on whitespace — so the\n * description would silently never associate with the frame.\n */\n const hintId = `${useId()}-hint`;\n\n const frameRef = useRef<HTMLDivElement>(null);\n const imageRef = useRef<HTMLImageElement | null>(null);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n from: Offset;\n } | null>(null);\n\n const [url, setUrl] = useState<string | null>(null);\n const [natural, setNatural] = useState<Size | null>(null);\n const [frame, setFrame] = useState<Size>({ width: 0, height: 0 });\n const [zoom, setZoom] = useState(1);\n const [offset, setOffset] = useState<Offset>({ x: 0, y: 0 });\n\n /**\n * Resolve `src` to a displayable URL.\n *\n * A `File`/`Blob` needs `createObjectURL`, and the URL must be revoked when the\n * source changes or the component unmounts — otherwise every re-pick of a photo\n * leaks the previous one for the lifetime of the document.\n */\n useEffect(() => {\n if (typeof src === \"string\") {\n setUrl(src);\n return;\n }\n const objectUrl = URL.createObjectURL(src);\n setUrl(objectUrl);\n return () => URL.revokeObjectURL(objectUrl);\n }, [src]);\n\n // A new source invalidates the previous framing.\n useEffect(() => {\n setNatural(null);\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n }, [url]);\n\n /** Track the frame's rendered size — the crop math is all relative to it. */\n useEffect(() => {\n const element = frameRef.current;\n if (!element) return;\n const measure = () =>\n setFrame({ width: element.clientWidth, height: element.clientHeight });\n measure();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, []);\n\n const scale = natural ? coverScale(natural, frame) * zoom : 0;\n\n /**\n * On-screen image size.\n *\n * Memoized because the pan callback depends on it: a fresh object every render\n * would rebuild that callback every render, and the pointer handlers close over\n * it during a drag.\n */\n const displayed = useMemo<Size>(\n () =>\n natural\n ? { width: natural.width * scale, height: natural.height * scale }\n : { width: 0, height: 0 },\n [natural, scale],\n );\n\n /** Apply a pan, clamped so the frame stays covered. */\n const pan = useCallback(\n (next: Offset) => {\n setOffset((current) => {\n const clamped = clampOffset(next, displayed, frame);\n if (clamped.x === current.x && clamped.y === current.y) return current;\n onCropChange?.({ zoom, offset: clamped });\n return clamped;\n });\n },\n [displayed, frame, onCropChange, zoom],\n );\n\n /**\n * Apply a zoom, then re-clamp the offset.\n *\n * Re-clamping is not optional: zooming *out* shrinks the image, so an offset\n * that was legal a moment ago can now expose background.\n */\n const applyZoom = useCallback(\n (next: number) => {\n const clampedZoom = Math.min(maxZoom, Math.max(1, next));\n setZoom(clampedZoom);\n if (!natural) return;\n const nextScale = coverScale(natural, frame) * clampedZoom;\n const nextDisplayed = {\n width: natural.width * nextScale,\n height: natural.height * nextScale,\n };\n setOffset((current) => {\n const clamped = clampOffset(current, nextDisplayed, frame);\n onCropChange?.({ zoom: clampedZoom, offset: clamped });\n return clamped;\n });\n },\n [frame, maxZoom, natural, onCropChange],\n );\n\n const reset = useCallback(() => {\n setZoom(1);\n setOffset({ x: 0, y: 0 });\n onCropChange?.({ zoom: 1, offset: { x: 0, y: 0 } });\n }, [onCropChange]);\n\n /**\n * Draw the current crop and encode it.\n *\n * Returns `null` rather than throwing on the paths a caller cannot do anything\n * about: no image yet, no 2D context, or an encoder that declined.\n */\n const crop = useCallback(async (): Promise<Blob | null> => {\n const image = imageRef.current;\n if (!image || !natural) return null;\n\n const rect = computeCropRect({ image: natural, frame, zoom, offset });\n if (rect.sWidth <= 0 || rect.sHeight <= 0) return null;\n\n const out = outputSize(rect, maxSize);\n const canvas = document.createElement(\"canvas\");\n canvas.width = out.width;\n canvas.height = out.height;\n const context = canvas.getContext(\"2d\");\n if (!context) return null;\n\n context.drawImage(\n image,\n rect.sx,\n rect.sy,\n rect.sWidth,\n rect.sHeight,\n 0,\n 0,\n out.width,\n out.height,\n );\n\n return new Promise((resolve) => {\n canvas.toBlob((blob) => resolve(blob), outputType, outputQuality);\n });\n }, [frame, maxSize, natural, offset, outputQuality, outputType, zoom]);\n\n useImperativeHandle(ref, () => ({ crop, reset }), [crop, reset]);\n\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (!natural) return;\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n from: offset,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n };\n\n const onPointerMove = (event: ReactPointerEvent<HTMLDivElement>): void => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n pan({\n x: drag.from.x + (event.clientX - drag.startX),\n y: drag.from.y + (event.clientY - drag.startY),\n });\n };\n\n const endDrag = (event: ReactPointerEvent<HTMLDivElement>): void => {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n const step = event.shiftKey ? KEY_STEP * 4 : KEY_STEP;\n const moves: Record<string, Offset> = {\n ArrowLeft: { x: -step, y: 0 },\n ArrowRight: { x: step, y: 0 },\n ArrowUp: { x: 0, y: -step },\n ArrowDown: { x: 0, y: step },\n };\n const move = moves[event.key];\n if (move) {\n event.preventDefault();\n pan({ x: offset.x + move.x, y: offset.y + move.y });\n return;\n }\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n applyZoom(zoom + ZOOM_STEP);\n } else if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n applyZoom(zoom - ZOOM_STEP);\n } else if (event.key === \"0\") {\n event.preventDefault();\n reset();\n }\n };\n\n return (\n <div className={cn(styles.wrapper, className)} {...rest}>\n <div\n ref={frameRef}\n className={cn(styles.frame, shape === \"circle\" && styles.circle)}\n style={{ aspectRatio: String(aspect) }}\n role=\"group\"\n aria-label={label}\n aria-describedby={hintId}\n tabIndex={0}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={endDrag}\n onPointerCancel={endDrag}\n onKeyDown={onKeyDown}\n onWheel={(event) => {\n event.preventDefault();\n applyZoom(zoom + (event.deltaY < 0 ? ZOOM_STEP : -ZOOM_STEP));\n }}\n >\n {url && (\n <img\n ref={imageRef}\n src={url}\n alt=\"\"\n draggable={false}\n className={styles.image}\n style={{\n width: displayed.width || undefined,\n height: displayed.height || undefined,\n transform: `translate(${offset.x}px, ${offset.y}px)`,\n }}\n onLoad={(event) => {\n const element = event.currentTarget;\n // A decode can succeed and still report no intrinsic size —\n // an SVG without a viewBox is the common case. Accepting\n // that would enable the controls over an image the crop\n // maths can do nothing with.\n if (element.naturalWidth > 0 && element.naturalHeight > 0) {\n setNatural({\n width: element.naturalWidth,\n height: element.naturalHeight,\n });\n }\n }}\n />\n )}\n </div>\n\n <div className={styles.controls}>\n <input\n type=\"range\"\n className={styles.zoom}\n min={1}\n max={maxZoom}\n step={0.01}\n value={zoom}\n onChange={(event) => applyZoom(Number(event.target.value))}\n aria-label=\"Zoom\"\n disabled={!natural}\n />\n <button type=\"button\" className={styles.reset} onClick={reset} disabled={!natural}>\n Centralizar\n </button>\n </div>\n\n <p id={hintId} className={styles.hint}>\n Arraste para reposicionar. Setas movem, <kbd>+</kbd> e <kbd>−</kbd> dão zoom,{\" \"}\n <kbd>0</kbd> centraliza.\n </p>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.module.cjs","names":[],"sources":["../../../src/components/Markdown/Markdown.module.css"],"sourcesContent":[".root {\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-relaxed);\n overflow-wrap: anywhere;\n}\n\n/*\n * Every block spaces itself with `margin-block-end` and the last child clears it,\n * so a Markdown body dropped into a card does not add a phantom gap at the bottom.\n */\n.root > * {\n margin-block: 0 var(--tempest-space-3);\n}\n\n.root > *:last-child {\n margin-block-end: 0;\n}\n\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n margin-block-start: var(--tempest-space-5);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-tight);\n}\n\n.root > .h1:first-child,\n.root > .h2:first-child,\n.root > .h3:first-child,\n.root > .h4:first-child,\n.root > .h5:first-child,\n.root > .h6:first-child {\n margin-block-start: 0;\n}\n\n.h1 {\n font-size: var(--tempest-text-2xl);\n}\n\n.h2 {\n font-size: var(--tempest-text-xl);\n}\n\n.h3 {\n font-size: var(--tempest-text-lg);\n}\n\n.h4,\n.h5,\n.h6 {\n font-size: var(--tempest-text-base);\n}\n\n.list {\n padding-inline-start: var(--tempest-space-6);\n}\n\n.list .list {\n margin-block: var(--tempest-space-1) 0;\n}\n\n.item {\n margin-block-end: var(--tempest-space-1);\n}\n\n.item > p {\n margin: 0;\n}\n\n.quote {\n padding-inline-start: var(--tempest-space-4);\n border-inline-start: 3px solid var(--tempest-border-strong);\n color: var(--tempest-text-muted);\n}\n\n.rule {\n height: 1px;\n border: 0;\n background-color: var(--tempest-border);\n}\n\n.inlineCode {\n padding: 0.1em 0.35em;\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface-2);\n color: var(--tempest-code-text, var(--tempest-text));\n font-family: var(--tempest-font-mono);\n font-size: 0.9em;\n}\n\n.link {\n color: var(--tempest-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n\n.image {\n max-width: 100%;\n height: auto;\n border-radius: var(--tempest-radius-md);\n}\n\n/*\n * A wide table scrolls inside its own box, and that box is focusable — a scroll\n * container with nothing focusable inside cannot be reached by keyboard, which is\n * the same defect the Table fix addressed.\n */\n.tableScroll {\n overflow-x: auto;\n}\n\n.tableScroll:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--tempest-text-sm);\n}\n\n.table th,\n.table td {\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border-bottom: 1px solid var(--tempest-border);\n text-align: left;\n}\n\n.table th {\n color: var(--tempest-text-muted);\n font-weight: var(--tempest-weight-semibold);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Markdown.module.cjs","names":[],"sources":["../../../src/components/Markdown/Markdown.module.css"],"sourcesContent":[".root {\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-relaxed);\n overflow-wrap: anywhere;\n}\n\n/*\n * Every block spaces itself with `margin-block-end` and the last child clears it,\n * so a Markdown body dropped into a card does not add a phantom gap at the bottom.\n */\n.root > * {\n margin-block: 0 var(--tempest-space-3);\n}\n\n.root > *:last-child {\n margin-block-end: 0;\n}\n\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n margin-block-start: var(--tempest-space-5);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-tight);\n}\n\n.root > .h1:first-child,\n.root > .h2:first-child,\n.root > .h3:first-child,\n.root > .h4:first-child,\n.root > .h5:first-child,\n.root > .h6:first-child {\n margin-block-start: 0;\n}\n\n.h1 {\n font-size: var(--tempest-text-2xl);\n}\n\n.h2 {\n font-size: var(--tempest-text-xl);\n}\n\n.h3 {\n font-size: var(--tempest-text-lg);\n}\n\n.h4,\n.h5,\n.h6 {\n font-size: var(--tempest-text-base);\n}\n\n.list {\n padding-inline-start: var(--tempest-space-6);\n}\n\n.list .list {\n margin-block: var(--tempest-space-1) 0;\n}\n\n.item {\n margin-block-end: var(--tempest-space-1);\n}\n\n.item > p {\n margin: 0;\n}\n\n.quote {\n padding-inline-start: var(--tempest-space-4);\n border-inline-start: 3px solid var(--tempest-border-strong);\n color: var(--tempest-text-muted);\n}\n\n.rule {\n height: 1px;\n border: 0;\n background-color: var(--tempest-border);\n}\n\n.inlineCode {\n padding: 0.1em 0.35em;\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface-2);\n color: var(--tempest-text);\n font-family: var(--tempest-font-mono);\n font-size: 0.9em;\n}\n\n.link {\n color: var(--tempest-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n\n.image {\n max-width: 100%;\n height: auto;\n border-radius: var(--tempest-radius-md);\n}\n\n/*\n * A wide table scrolls inside its own box, and that box is focusable — a scroll\n * container with nothing focusable inside cannot be reached by keyboard, which is\n * the same defect the Table fix addressed.\n */\n.tableScroll {\n overflow-x: auto;\n}\n\n.tableScroll:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--tempest-text-sm);\n}\n\n.table th,\n.table td {\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border-bottom: 1px solid var(--tempest-border);\n text-align: left;\n}\n\n.table th {\n color: var(--tempest-text-muted);\n font-weight: var(--tempest-weight-semibold);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.module.js","names":[],"sources":["../../../src/components/Markdown/Markdown.module.css"],"sourcesContent":[".root {\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-relaxed);\n overflow-wrap: anywhere;\n}\n\n/*\n * Every block spaces itself with `margin-block-end` and the last child clears it,\n * so a Markdown body dropped into a card does not add a phantom gap at the bottom.\n */\n.root > * {\n margin-block: 0 var(--tempest-space-3);\n}\n\n.root > *:last-child {\n margin-block-end: 0;\n}\n\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n margin-block-start: var(--tempest-space-5);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-tight);\n}\n\n.root > .h1:first-child,\n.root > .h2:first-child,\n.root > .h3:first-child,\n.root > .h4:first-child,\n.root > .h5:first-child,\n.root > .h6:first-child {\n margin-block-start: 0;\n}\n\n.h1 {\n font-size: var(--tempest-text-2xl);\n}\n\n.h2 {\n font-size: var(--tempest-text-xl);\n}\n\n.h3 {\n font-size: var(--tempest-text-lg);\n}\n\n.h4,\n.h5,\n.h6 {\n font-size: var(--tempest-text-base);\n}\n\n.list {\n padding-inline-start: var(--tempest-space-6);\n}\n\n.list .list {\n margin-block: var(--tempest-space-1) 0;\n}\n\n.item {\n margin-block-end: var(--tempest-space-1);\n}\n\n.item > p {\n margin: 0;\n}\n\n.quote {\n padding-inline-start: var(--tempest-space-4);\n border-inline-start: 3px solid var(--tempest-border-strong);\n color: var(--tempest-text-muted);\n}\n\n.rule {\n height: 1px;\n border: 0;\n background-color: var(--tempest-border);\n}\n\n.inlineCode {\n padding: 0.1em 0.35em;\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface-2);\n color: var(--tempest-code-text, var(--tempest-text));\n font-family: var(--tempest-font-mono);\n font-size: 0.9em;\n}\n\n.link {\n color: var(--tempest-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n\n.image {\n max-width: 100%;\n height: auto;\n border-radius: var(--tempest-radius-md);\n}\n\n/*\n * A wide table scrolls inside its own box, and that box is focusable — a scroll\n * container with nothing focusable inside cannot be reached by keyboard, which is\n * the same defect the Table fix addressed.\n */\n.tableScroll {\n overflow-x: auto;\n}\n\n.tableScroll:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--tempest-text-sm);\n}\n\n.table th,\n.table td {\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border-bottom: 1px solid var(--tempest-border);\n text-align: left;\n}\n\n.table th {\n color: var(--tempest-text-muted);\n font-weight: var(--tempest-weight-semibold);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Markdown.module.js","names":[],"sources":["../../../src/components/Markdown/Markdown.module.css"],"sourcesContent":[".root {\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-base);\n line-height: var(--tempest-leading-relaxed);\n overflow-wrap: anywhere;\n}\n\n/*\n * Every block spaces itself with `margin-block-end` and the last child clears it,\n * so a Markdown body dropped into a card does not add a phantom gap at the bottom.\n */\n.root > * {\n margin-block: 0 var(--tempest-space-3);\n}\n\n.root > *:last-child {\n margin-block-end: 0;\n}\n\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n margin-block-start: var(--tempest-space-5);\n font-weight: var(--tempest-weight-semibold);\n line-height: var(--tempest-leading-tight);\n}\n\n.root > .h1:first-child,\n.root > .h2:first-child,\n.root > .h3:first-child,\n.root > .h4:first-child,\n.root > .h5:first-child,\n.root > .h6:first-child {\n margin-block-start: 0;\n}\n\n.h1 {\n font-size: var(--tempest-text-2xl);\n}\n\n.h2 {\n font-size: var(--tempest-text-xl);\n}\n\n.h3 {\n font-size: var(--tempest-text-lg);\n}\n\n.h4,\n.h5,\n.h6 {\n font-size: var(--tempest-text-base);\n}\n\n.list {\n padding-inline-start: var(--tempest-space-6);\n}\n\n.list .list {\n margin-block: var(--tempest-space-1) 0;\n}\n\n.item {\n margin-block-end: var(--tempest-space-1);\n}\n\n.item > p {\n margin: 0;\n}\n\n.quote {\n padding-inline-start: var(--tempest-space-4);\n border-inline-start: 3px solid var(--tempest-border-strong);\n color: var(--tempest-text-muted);\n}\n\n.rule {\n height: 1px;\n border: 0;\n background-color: var(--tempest-border);\n}\n\n.inlineCode {\n padding: 0.1em 0.35em;\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-surface-2);\n color: var(--tempest-text);\n font-family: var(--tempest-font-mono);\n font-size: 0.9em;\n}\n\n.link {\n color: var(--tempest-primary);\n text-decoration: underline;\n text-underline-offset: 2px;\n}\n\n.image {\n max-width: 100%;\n height: auto;\n border-radius: var(--tempest-radius-md);\n}\n\n/*\n * A wide table scrolls inside its own box, and that box is focusable — a scroll\n * container with nothing focusable inside cannot be reached by keyboard, which is\n * the same defect the Table fix addressed.\n */\n.tableScroll {\n overflow-x: auto;\n}\n\n.tableScroll:focus-visible {\n outline: 2px solid var(--tempest-primary);\n outline-offset: 2px;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--tempest-text-sm);\n}\n\n.table th,\n.table td {\n padding: var(--tempest-space-2) var(--tempest-space-3);\n border-bottom: 1px solid var(--tempest-border);\n text-align: left;\n}\n\n.table th {\n color: var(--tempest-text-muted);\n font-weight: var(--tempest-weight-semibold);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordInput.module.cjs","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n transition: border-color var(--tempest-duration-fast, 120ms);\n}\n\n.field:focus-within {\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width, 2px)\n var(--tempest-focus-ring-color, var(--tempest-primary-100));\n}\n\n.input {\n flex: 1 1 auto;\n border: 0;\n background: transparent;\n outline: 0;\n color: var(--tempest-text);\n font: inherit;\n font-family: var(--tempest-font-sans);\n}\n\n.sm .input {\n padding: 6px 8px;\n font-size: var(--tempest-text-sm);\n}\n\n.md .input {\n padding: 8px 12px;\n font-size: var(--tempest-text-md);\n}\n\n.lg .input {\n padding: 10px 14px;\n font-size: var(--tempest-text-lg);\n}\n\n.toggle {\n flex: 0 0 auto;\n background: none;\n border: 0;\n cursor: pointer;\n padding: 0 12px;\n font-size: 16px;\n color: var(--tempest-text-muted);\n}\n\n.toggle:hover {\n color: var(--tempest-text);\n}\n\n.error .field {\n border-color: var(--tempest-danger-border, var(--tempest-danger));\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger-fg, var(--tempest-danger));\n}\n\n.strength {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.strengthBar {\n flex: 1 1 auto;\n height: 4px;\n background: var(--tempest-gray-200, var(--tempest-border));\n border-radius: var(--tempest-radius-full);\n overflow: hidden;\n}\n\n.strengthBar > span {\n display: block;\n height: 100%;\n transition: width var(--tempest-duration-base, 200ms);\n}\n\n.strengthLabel {\n color: var(--tempest-text-muted);\n flex: 0 0 auto;\n}\n\n.level0 .strengthBar > span,\n.level1 .strengthBar > span {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n\n.level2 .strengthBar > span {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n\n.level3 .strengthBar > span,\n.level4 .strengthBar > span {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n"],"mappings":""}
1
+ {"version":3,"file":"PasswordInput.module.cjs","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n transition: border-color var(--tempest-duration-fast, 120ms);\n}\n\n.field:focus-within {\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width, 2px)\n var(--tempest-focus-ring-color, var(--tempest-primary-100));\n}\n\n.input {\n flex: 1 1 auto;\n border: 0;\n background: transparent;\n outline: 0;\n color: var(--tempest-text);\n font: inherit;\n font-family: var(--tempest-font-sans);\n}\n\n.sm .input {\n padding: 6px 8px;\n font-size: var(--tempest-text-sm);\n}\n\n.md .input {\n padding: 8px 12px;\n font-size: var(--tempest-text-md);\n}\n\n.lg .input {\n padding: 10px 14px;\n font-size: var(--tempest-text-lg);\n}\n\n.toggle {\n flex: 0 0 auto;\n background: none;\n border: 0;\n cursor: pointer;\n padding: 0 12px;\n font-size: 16px;\n color: var(--tempest-text-muted);\n}\n\n.toggle:hover {\n color: var(--tempest-text);\n}\n\n.error .field {\n border-color: var(--tempest-danger-border, var(--tempest-danger));\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger-fg, var(--tempest-danger));\n}\n\n.strength {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.strengthBar {\n flex: 1 1 auto;\n height: 4px;\n background: var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n overflow: hidden;\n}\n\n.strengthBar > span {\n display: block;\n height: 100%;\n transition: width var(--tempest-duration-base, 200ms);\n}\n\n.strengthLabel {\n color: var(--tempest-text-muted);\n flex: 0 0 auto;\n}\n\n.level0 .strengthBar > span,\n.level1 .strengthBar > span {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n\n.level2 .strengthBar > span {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n\n.level3 .strengthBar > span,\n.level4 .strengthBar > span {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordInput.module.js","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n transition: border-color var(--tempest-duration-fast, 120ms);\n}\n\n.field:focus-within {\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width, 2px)\n var(--tempest-focus-ring-color, var(--tempest-primary-100));\n}\n\n.input {\n flex: 1 1 auto;\n border: 0;\n background: transparent;\n outline: 0;\n color: var(--tempest-text);\n font: inherit;\n font-family: var(--tempest-font-sans);\n}\n\n.sm .input {\n padding: 6px 8px;\n font-size: var(--tempest-text-sm);\n}\n\n.md .input {\n padding: 8px 12px;\n font-size: var(--tempest-text-md);\n}\n\n.lg .input {\n padding: 10px 14px;\n font-size: var(--tempest-text-lg);\n}\n\n.toggle {\n flex: 0 0 auto;\n background: none;\n border: 0;\n cursor: pointer;\n padding: 0 12px;\n font-size: 16px;\n color: var(--tempest-text-muted);\n}\n\n.toggle:hover {\n color: var(--tempest-text);\n}\n\n.error .field {\n border-color: var(--tempest-danger-border, var(--tempest-danger));\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger-fg, var(--tempest-danger));\n}\n\n.strength {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.strengthBar {\n flex: 1 1 auto;\n height: 4px;\n background: var(--tempest-gray-200, var(--tempest-border));\n border-radius: var(--tempest-radius-full);\n overflow: hidden;\n}\n\n.strengthBar > span {\n display: block;\n height: 100%;\n transition: width var(--tempest-duration-base, 200ms);\n}\n\n.strengthLabel {\n color: var(--tempest-text-muted);\n flex: 0 0 auto;\n}\n\n.level0 .strengthBar > span,\n.level1 .strengthBar > span {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n\n.level2 .strengthBar > span {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n\n.level3 .strengthBar > span,\n.level4 .strengthBar > span {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n"],"mappings":""}
1
+ {"version":3,"file":"PasswordInput.module.js","names":[],"sources":["../../../src/components/PasswordInput/PasswordInput.module.css"],"sourcesContent":[".wrapper {\n display: flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n width: 100%;\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.field {\n position: relative;\n display: flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n transition: border-color var(--tempest-duration-fast, 120ms);\n}\n\n.field:focus-within {\n border-color: var(--tempest-primary);\n box-shadow: 0 0 0 var(--tempest-focus-ring-width, 2px)\n var(--tempest-focus-ring-color, var(--tempest-primary-100));\n}\n\n.input {\n flex: 1 1 auto;\n border: 0;\n background: transparent;\n outline: 0;\n color: var(--tempest-text);\n font: inherit;\n font-family: var(--tempest-font-sans);\n}\n\n.sm .input {\n padding: 6px 8px;\n font-size: var(--tempest-text-sm);\n}\n\n.md .input {\n padding: 8px 12px;\n font-size: var(--tempest-text-md);\n}\n\n.lg .input {\n padding: 10px 14px;\n font-size: var(--tempest-text-lg);\n}\n\n.toggle {\n flex: 0 0 auto;\n background: none;\n border: 0;\n cursor: pointer;\n padding: 0 12px;\n font-size: 16px;\n color: var(--tempest-text-muted);\n}\n\n.toggle:hover {\n color: var(--tempest-text);\n}\n\n.error .field {\n border-color: var(--tempest-danger-border, var(--tempest-danger));\n}\n\n.helper {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n}\n\n.errorText {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-danger-fg, var(--tempest-danger));\n}\n\n.strength {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.strengthBar {\n flex: 1 1 auto;\n height: 4px;\n background: var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n overflow: hidden;\n}\n\n.strengthBar > span {\n display: block;\n height: 100%;\n transition: width var(--tempest-duration-base, 200ms);\n}\n\n.strengthLabel {\n color: var(--tempest-text-muted);\n flex: 0 0 auto;\n}\n\n.level0 .strengthBar > span,\n.level1 .strengthBar > span {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n\n.level2 .strengthBar > span {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n\n.level3 .strengthBar > span,\n.level4 .strengthBar > span {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControl.module.cjs","names":[],"sources":["../../../src/components/SegmentedControl/SegmentedControl.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n background: var(--tempest-gray-100);\n border-radius: var(--tempest-radius-md);\n padding: 2px;\n font-family: var(--tempest-font-sans);\n gap: 0;\n}\n\n.group.fullWidth {\n display: flex;\n width: 100%;\n}\n\n.segment {\n flex: 1 1 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-1);\n padding: 6px 12px;\n border: 0;\n background: transparent;\n color: var(--tempest-text-muted);\n cursor: pointer;\n border-radius: calc(var(--tempest-radius-md) - 2px);\n font-weight: var(--tempest-weight-medium);\n transition:\n background var(--tempest-duration-fast, 120ms),\n color var(--tempest-duration-fast, 120ms);\n white-space: nowrap;\n}\n\n.group.sm .segment {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n min-height: 24px;\n}\n\n.group.md .segment {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n min-height: 32px;\n}\n\n.group.lg .segment {\n padding: 8px 14px;\n font-size: var(--tempest-text-md);\n min-height: 40px;\n}\n\n.segment:hover {\n color: var(--tempest-text);\n}\n\n.segment.active {\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.08));\n}\n\n.segment:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"SegmentedControl.module.cjs","names":[],"sources":["../../../src/components/SegmentedControl/SegmentedControl.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n background: var(--tempest-surface-2);\n border-radius: var(--tempest-radius-md);\n padding: 2px;\n font-family: var(--tempest-font-sans);\n gap: 0;\n}\n\n.group.fullWidth {\n display: flex;\n width: 100%;\n}\n\n.segment {\n flex: 1 1 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-1);\n padding: 6px 12px;\n border: 0;\n background: transparent;\n color: var(--tempest-text-muted);\n cursor: pointer;\n border-radius: calc(var(--tempest-radius-md) - 2px);\n font-weight: var(--tempest-weight-medium);\n transition:\n background var(--tempest-duration-fast, 120ms),\n color var(--tempest-duration-fast, 120ms);\n white-space: nowrap;\n}\n\n.group.sm .segment {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n min-height: 24px;\n}\n\n.group.md .segment {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n min-height: 32px;\n}\n\n.group.lg .segment {\n padding: 8px 14px;\n font-size: var(--tempest-text-md);\n min-height: 40px;\n}\n\n.segment:hover {\n color: var(--tempest-text);\n}\n\n.segment.active {\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.08));\n}\n\n.segment:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControl.module.js","names":[],"sources":["../../../src/components/SegmentedControl/SegmentedControl.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n background: var(--tempest-gray-100);\n border-radius: var(--tempest-radius-md);\n padding: 2px;\n font-family: var(--tempest-font-sans);\n gap: 0;\n}\n\n.group.fullWidth {\n display: flex;\n width: 100%;\n}\n\n.segment {\n flex: 1 1 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-1);\n padding: 6px 12px;\n border: 0;\n background: transparent;\n color: var(--tempest-text-muted);\n cursor: pointer;\n border-radius: calc(var(--tempest-radius-md) - 2px);\n font-weight: var(--tempest-weight-medium);\n transition:\n background var(--tempest-duration-fast, 120ms),\n color var(--tempest-duration-fast, 120ms);\n white-space: nowrap;\n}\n\n.group.sm .segment {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n min-height: 24px;\n}\n\n.group.md .segment {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n min-height: 32px;\n}\n\n.group.lg .segment {\n padding: 8px 14px;\n font-size: var(--tempest-text-md);\n min-height: 40px;\n}\n\n.segment:hover {\n color: var(--tempest-text);\n}\n\n.segment.active {\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.08));\n}\n\n.segment:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"SegmentedControl.module.js","names":[],"sources":["../../../src/components/SegmentedControl/SegmentedControl.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n background: var(--tempest-surface-2);\n border-radius: var(--tempest-radius-md);\n padding: 2px;\n font-family: var(--tempest-font-sans);\n gap: 0;\n}\n\n.group.fullWidth {\n display: flex;\n width: 100%;\n}\n\n.segment {\n flex: 1 1 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-1);\n padding: 6px 12px;\n border: 0;\n background: transparent;\n color: var(--tempest-text-muted);\n cursor: pointer;\n border-radius: calc(var(--tempest-radius-md) - 2px);\n font-weight: var(--tempest-weight-medium);\n transition:\n background var(--tempest-duration-fast, 120ms),\n color var(--tempest-duration-fast, 120ms);\n white-space: nowrap;\n}\n\n.group.sm .segment {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n min-height: 24px;\n}\n\n.group.md .segment {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n min-height: 32px;\n}\n\n.group.lg .segment {\n padding: 8px 14px;\n font-size: var(--tempest-text-md);\n min-height: 40px;\n}\n\n.segment:hover {\n color: var(--tempest-text);\n}\n\n.segment.active {\n background: var(--tempest-surface);\n color: var(--tempest-text);\n box-shadow: var(--tempest-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.08));\n}\n\n.segment:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n}\n\n.label {\n line-height: 1;\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.module.cjs","names":[],"sources":["../../../src/components/Sidebar/Sidebar.module.css"],"sourcesContent":[".sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--tempest-surface);\n border-right: 1px solid var(--tempest-border);\n font-family: var(--tempest-font-sans);\n transition: width var(--tempest-duration-base, 200ms) var(--tempest-ease-out, ease-out);\n overflow: hidden;\n}\n\n.header {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-bottom: 1px solid var(--tempest-border);\n min-height: 56px;\n display: flex;\n align-items: center;\n}\n\n.nav {\n flex: 1 1 auto;\n overflow-y: auto;\n padding: var(--tempest-space-2);\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group + .group {\n margin-top: var(--tempest-space-3);\n}\n\n.collapsed .group + .group {\n margin-top: var(--tempest-space-2);\n padding-top: var(--tempest-space-2);\n border-top: 1px solid var(--tempest-border);\n}\n\n.section {\n padding: var(--tempest-space-2) var(--tempest-space-3) var(--tempest-space-1);\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n font-weight: var(--tempest-weight-semibold);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sectionCollapsed {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n.separator {\n flex: 0 0 auto;\n margin: var(--tempest-space-2) var(--tempest-space-1);\n border: 0;\n border-top: 1px solid var(--tempest-border);\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: 0;\n border-radius: var(--tempest-radius-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-sm);\n text-align: left;\n cursor: pointer;\n transition: background var(--tempest-duration-fast, 120ms);\n min-height: 36px;\n width: 100%;\n text-decoration: none;\n}\n\n.collapsed .item {\n justify-content: center;\n padding-left: 0;\n padding-right: 0;\n}\n\n.item:hover {\n background: var(--tempest-gray-100);\n}\n\n.item.active {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n font-weight: var(--tempest-weight-medium);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n font-size: 18px;\n line-height: 1;\n flex: 0 0 auto;\n}\n\n.label {\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.badge {\n flex: 0 0 auto;\n min-width: 18px;\n height: 18px;\n padding: 0 6px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-gray-200);\n color: var(--tempest-text);\n font-size: 10px;\n line-height: 18px;\n text-align: center;\n}\n\n.footer {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-top: 1px solid var(--tempest-border);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Sidebar.module.cjs","names":[],"sources":["../../../src/components/Sidebar/Sidebar.module.css"],"sourcesContent":[".sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--tempest-surface);\n border-right: 1px solid var(--tempest-border);\n font-family: var(--tempest-font-sans);\n transition: width var(--tempest-duration-base, 200ms) var(--tempest-ease-out, ease-out);\n overflow: hidden;\n}\n\n.header {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-bottom: 1px solid var(--tempest-border);\n min-height: 56px;\n display: flex;\n align-items: center;\n}\n\n.nav {\n flex: 1 1 auto;\n overflow-y: auto;\n padding: var(--tempest-space-2);\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group + .group {\n margin-top: var(--tempest-space-3);\n}\n\n.collapsed .group + .group {\n margin-top: var(--tempest-space-2);\n padding-top: var(--tempest-space-2);\n border-top: 1px solid var(--tempest-border);\n}\n\n.section {\n padding: var(--tempest-space-2) var(--tempest-space-3) var(--tempest-space-1);\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n font-weight: var(--tempest-weight-semibold);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sectionCollapsed {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n.separator {\n flex: 0 0 auto;\n margin: var(--tempest-space-2) var(--tempest-space-1);\n border: 0;\n border-top: 1px solid var(--tempest-border);\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: 0;\n border-radius: var(--tempest-radius-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-sm);\n text-align: left;\n cursor: pointer;\n transition: background var(--tempest-duration-fast, 120ms);\n min-height: 36px;\n width: 100%;\n text-decoration: none;\n}\n\n.collapsed .item {\n justify-content: center;\n padding-left: 0;\n padding-right: 0;\n}\n\n.item:hover {\n background: var(--tempest-surface-2);\n}\n\n.item.active {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n font-weight: var(--tempest-weight-medium);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n font-size: 18px;\n line-height: 1;\n flex: 0 0 auto;\n}\n\n.label {\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.badge {\n flex: 0 0 auto;\n min-width: 18px;\n height: 18px;\n padding: 0 6px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-surface-3);\n color: var(--tempest-text);\n font-size: 10px;\n line-height: 18px;\n text-align: center;\n}\n\n.footer {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-top: 1px solid var(--tempest-border);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.module.js","names":[],"sources":["../../../src/components/Sidebar/Sidebar.module.css"],"sourcesContent":[".sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--tempest-surface);\n border-right: 1px solid var(--tempest-border);\n font-family: var(--tempest-font-sans);\n transition: width var(--tempest-duration-base, 200ms) var(--tempest-ease-out, ease-out);\n overflow: hidden;\n}\n\n.header {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-bottom: 1px solid var(--tempest-border);\n min-height: 56px;\n display: flex;\n align-items: center;\n}\n\n.nav {\n flex: 1 1 auto;\n overflow-y: auto;\n padding: var(--tempest-space-2);\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group + .group {\n margin-top: var(--tempest-space-3);\n}\n\n.collapsed .group + .group {\n margin-top: var(--tempest-space-2);\n padding-top: var(--tempest-space-2);\n border-top: 1px solid var(--tempest-border);\n}\n\n.section {\n padding: var(--tempest-space-2) var(--tempest-space-3) var(--tempest-space-1);\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n font-weight: var(--tempest-weight-semibold);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sectionCollapsed {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n.separator {\n flex: 0 0 auto;\n margin: var(--tempest-space-2) var(--tempest-space-1);\n border: 0;\n border-top: 1px solid var(--tempest-border);\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: 0;\n border-radius: var(--tempest-radius-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-sm);\n text-align: left;\n cursor: pointer;\n transition: background var(--tempest-duration-fast, 120ms);\n min-height: 36px;\n width: 100%;\n text-decoration: none;\n}\n\n.collapsed .item {\n justify-content: center;\n padding-left: 0;\n padding-right: 0;\n}\n\n.item:hover {\n background: var(--tempest-gray-100);\n}\n\n.item.active {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n font-weight: var(--tempest-weight-medium);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n font-size: 18px;\n line-height: 1;\n flex: 0 0 auto;\n}\n\n.label {\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.badge {\n flex: 0 0 auto;\n min-width: 18px;\n height: 18px;\n padding: 0 6px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-gray-200);\n color: var(--tempest-text);\n font-size: 10px;\n line-height: 18px;\n text-align: center;\n}\n\n.footer {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-top: 1px solid var(--tempest-border);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Sidebar.module.js","names":[],"sources":["../../../src/components/Sidebar/Sidebar.module.css"],"sourcesContent":[".sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--tempest-surface);\n border-right: 1px solid var(--tempest-border);\n font-family: var(--tempest-font-sans);\n transition: width var(--tempest-duration-base, 200ms) var(--tempest-ease-out, ease-out);\n overflow: hidden;\n}\n\n.header {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-bottom: 1px solid var(--tempest-border);\n min-height: 56px;\n display: flex;\n align-items: center;\n}\n\n.nav {\n flex: 1 1 auto;\n overflow-y: auto;\n padding: var(--tempest-space-2);\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.group + .group {\n margin-top: var(--tempest-space-3);\n}\n\n.collapsed .group + .group {\n margin-top: var(--tempest-space-2);\n padding-top: var(--tempest-space-2);\n border-top: 1px solid var(--tempest-border);\n}\n\n.section {\n padding: var(--tempest-space-2) var(--tempest-space-3) var(--tempest-space-1);\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-xs);\n font-weight: var(--tempest-weight-semibold);\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.sectionCollapsed {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n.separator {\n flex: 0 0 auto;\n margin: var(--tempest-space-2) var(--tempest-space-1);\n border: 0;\n border-top: 1px solid var(--tempest-border);\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--tempest-space-3);\n padding: var(--tempest-space-2) var(--tempest-space-3);\n background: none;\n border: 0;\n border-radius: var(--tempest-radius-md);\n color: var(--tempest-text);\n font-size: var(--tempest-text-sm);\n text-align: left;\n cursor: pointer;\n transition: background var(--tempest-duration-fast, 120ms);\n min-height: 36px;\n width: 100%;\n text-decoration: none;\n}\n\n.collapsed .item {\n justify-content: center;\n padding-left: 0;\n padding-right: 0;\n}\n\n.item:hover {\n background: var(--tempest-surface-2);\n}\n\n.item.active {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n font-weight: var(--tempest-weight-medium);\n}\n\n.item:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n align-items: center;\n font-size: 18px;\n line-height: 1;\n flex: 0 0 auto;\n}\n\n.label {\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.badge {\n flex: 0 0 auto;\n min-width: 18px;\n height: 18px;\n padding: 0 6px;\n border-radius: var(--tempest-radius-full);\n background: var(--tempest-surface-3);\n color: var(--tempest-text);\n font-size: 10px;\n line-height: 18px;\n text-align: center;\n}\n\n.footer {\n padding: var(--tempest-space-3) var(--tempest-space-4);\n border-top: 1px solid var(--tempest-border);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"StepperInput.module.cjs","names":[],"sources":["../../../src/components/StepperInput/StepperInput.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.row {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n overflow: hidden;\n}\n\n.row.sm {\n font-size: var(--tempest-text-sm);\n}\n.row.md {\n font-size: var(--tempest-text-md);\n}\n.row.lg {\n font-size: var(--tempest-text-lg);\n}\n\n.row.disabled {\n opacity: 0.5;\n}\n\n.btn {\n background: transparent;\n border: 0;\n color: var(--tempest-text);\n cursor: pointer;\n line-height: 1;\n font: inherit;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.row.sm .btn {\n width: 28px;\n height: 28px;\n}\n\n.row.md .btn {\n width: 36px;\n height: 36px;\n}\n\n.row.lg .btn {\n width: 44px;\n height: 44px;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--tempest-gray-100);\n}\n\n.btn:disabled {\n color: var(--tempest-text-muted);\n cursor: not-allowed;\n}\n\n.value {\n min-width: 2ch;\n padding: 0 var(--tempest-space-3);\n text-align: center;\n font-variant-numeric: tabular-nums;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"StepperInput.module.cjs","names":[],"sources":["../../../src/components/StepperInput/StepperInput.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.row {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n overflow: hidden;\n}\n\n.row.sm {\n font-size: var(--tempest-text-sm);\n}\n.row.md {\n font-size: var(--tempest-text-md);\n}\n.row.lg {\n font-size: var(--tempest-text-lg);\n}\n\n.row.disabled {\n opacity: 0.5;\n}\n\n.btn {\n background: transparent;\n border: 0;\n color: var(--tempest-text);\n cursor: pointer;\n line-height: 1;\n font: inherit;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.row.sm .btn {\n width: 28px;\n height: 28px;\n}\n\n.row.md .btn {\n width: 36px;\n height: 36px;\n}\n\n.row.lg .btn {\n width: 44px;\n height: 44px;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--tempest-surface-2);\n}\n\n.btn:disabled {\n color: var(--tempest-text-muted);\n cursor: not-allowed;\n}\n\n.value {\n min-width: 2ch;\n padding: 0 var(--tempest-space-3);\n text-align: center;\n font-variant-numeric: tabular-nums;\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"StepperInput.module.js","names":[],"sources":["../../../src/components/StepperInput/StepperInput.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.row {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n overflow: hidden;\n}\n\n.row.sm {\n font-size: var(--tempest-text-sm);\n}\n.row.md {\n font-size: var(--tempest-text-md);\n}\n.row.lg {\n font-size: var(--tempest-text-lg);\n}\n\n.row.disabled {\n opacity: 0.5;\n}\n\n.btn {\n background: transparent;\n border: 0;\n color: var(--tempest-text);\n cursor: pointer;\n line-height: 1;\n font: inherit;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.row.sm .btn {\n width: 28px;\n height: 28px;\n}\n\n.row.md .btn {\n width: 36px;\n height: 36px;\n}\n\n.row.lg .btn {\n width: 44px;\n height: 44px;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--tempest-gray-100);\n}\n\n.btn:disabled {\n color: var(--tempest-text-muted);\n cursor: not-allowed;\n}\n\n.value {\n min-width: 2ch;\n padding: 0 var(--tempest-space-3);\n text-align: center;\n font-variant-numeric: tabular-nums;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"StepperInput.module.js","names":[],"sources":["../../../src/components/StepperInput/StepperInput.module.css"],"sourcesContent":[".wrapper {\n display: inline-flex;\n flex-direction: column;\n gap: var(--tempest-space-1);\n font-family: var(--tempest-font-sans);\n}\n\n.label {\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n color: var(--tempest-text);\n}\n\n.row {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background: var(--tempest-surface);\n overflow: hidden;\n}\n\n.row.sm {\n font-size: var(--tempest-text-sm);\n}\n.row.md {\n font-size: var(--tempest-text-md);\n}\n.row.lg {\n font-size: var(--tempest-text-lg);\n}\n\n.row.disabled {\n opacity: 0.5;\n}\n\n.btn {\n background: transparent;\n border: 0;\n color: var(--tempest-text);\n cursor: pointer;\n line-height: 1;\n font: inherit;\n font-weight: var(--tempest-weight-semibold);\n}\n\n.row.sm .btn {\n width: 28px;\n height: 28px;\n}\n\n.row.md .btn {\n width: 36px;\n height: 36px;\n}\n\n.row.lg .btn {\n width: 44px;\n height: 44px;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--tempest-surface-2);\n}\n\n.btn:disabled {\n color: var(--tempest-text-muted);\n cursor: not-allowed;\n}\n\n.value {\n min-width: 2ch;\n padding: 0 var(--tempest-space-3);\n text-align: center;\n font-variant-numeric: tabular-nums;\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Tag.module.cjs","names":[],"sources":["../../../src/components/Tag/Tag.module.css"],"sourcesContent":[".tag {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n border-radius: var(--tempest-radius-full);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: 1;\n}\n\n.tag.sm {\n padding: 2px 8px;\n font-size: var(--tempest-text-2xs);\n}\n\n.tag.md {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n}\n\n.tag.lg {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n}\n\n.tag.neutral {\n background: var(--tempest-gray-100);\n color: var(--tempest-text);\n}\n\n.tag.primary {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n}\n\n.tag.success {\n background: var(--tempest-success-bg);\n color: var(--tempest-success-fg);\n}\n\n.tag.warning {\n background: var(--tempest-warning-bg);\n color: var(--tempest-warning-fg);\n}\n\n.tag.danger {\n background: var(--tempest-danger-bg);\n color: var(--tempest-danger-fg);\n}\n\n.tag.info {\n background: var(--tempest-info-bg);\n color: var(--tempest-info-fg);\n}\n\n.label {\n line-height: 1.2;\n}\n\n.remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: currentColor;\n cursor: pointer;\n padding: 0;\n width: 16px;\n height: 16px;\n border-radius: var(--tempest-radius-full);\n font-size: 14px;\n line-height: 1;\n}\n\n.remove:hover {\n background: color-mix(in srgb, currentColor 15%, transparent);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Tag.module.cjs","names":[],"sources":["../../../src/components/Tag/Tag.module.css"],"sourcesContent":[".tag {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n border-radius: var(--tempest-radius-full);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: 1;\n}\n\n.tag.sm {\n padding: 2px 8px;\n font-size: var(--tempest-text-2xs);\n}\n\n.tag.md {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n}\n\n.tag.lg {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n}\n\n.tag.neutral {\n background: var(--tempest-surface-2);\n color: var(--tempest-text);\n}\n\n.tag.primary {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n}\n\n.tag.success {\n background: var(--tempest-success-bg);\n color: var(--tempest-success-fg);\n}\n\n.tag.warning {\n background: var(--tempest-warning-bg);\n color: var(--tempest-warning-fg);\n}\n\n.tag.danger {\n background: var(--tempest-danger-bg);\n color: var(--tempest-danger-fg);\n}\n\n.tag.info {\n background: var(--tempest-info-bg);\n color: var(--tempest-info-fg);\n}\n\n.label {\n line-height: 1.2;\n}\n\n.remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: currentColor;\n cursor: pointer;\n padding: 0;\n width: 16px;\n height: 16px;\n border-radius: var(--tempest-radius-full);\n font-size: 14px;\n line-height: 1;\n}\n\n.remove:hover {\n background: color-mix(in srgb, currentColor 15%, transparent);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Tag.module.js","names":[],"sources":["../../../src/components/Tag/Tag.module.css"],"sourcesContent":[".tag {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n border-radius: var(--tempest-radius-full);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: 1;\n}\n\n.tag.sm {\n padding: 2px 8px;\n font-size: var(--tempest-text-2xs);\n}\n\n.tag.md {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n}\n\n.tag.lg {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n}\n\n.tag.neutral {\n background: var(--tempest-gray-100);\n color: var(--tempest-text);\n}\n\n.tag.primary {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n}\n\n.tag.success {\n background: var(--tempest-success-bg);\n color: var(--tempest-success-fg);\n}\n\n.tag.warning {\n background: var(--tempest-warning-bg);\n color: var(--tempest-warning-fg);\n}\n\n.tag.danger {\n background: var(--tempest-danger-bg);\n color: var(--tempest-danger-fg);\n}\n\n.tag.info {\n background: var(--tempest-info-bg);\n color: var(--tempest-info-fg);\n}\n\n.label {\n line-height: 1.2;\n}\n\n.remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: currentColor;\n cursor: pointer;\n padding: 0;\n width: 16px;\n height: 16px;\n border-radius: var(--tempest-radius-full);\n font-size: 14px;\n line-height: 1;\n}\n\n.remove:hover {\n background: color-mix(in srgb, currentColor 15%, transparent);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Tag.module.js","names":[],"sources":["../../../src/components/Tag/Tag.module.css"],"sourcesContent":[".tag {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n border-radius: var(--tempest-radius-full);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: 1;\n}\n\n.tag.sm {\n padding: 2px 8px;\n font-size: var(--tempest-text-2xs);\n}\n\n.tag.md {\n padding: 4px 10px;\n font-size: var(--tempest-text-xs);\n}\n\n.tag.lg {\n padding: 6px 12px;\n font-size: var(--tempest-text-sm);\n}\n\n.tag.neutral {\n background: var(--tempest-surface-2);\n color: var(--tempest-text);\n}\n\n.tag.primary {\n background: var(--tempest-primary-100);\n color: var(--tempest-primary-700);\n}\n\n.tag.success {\n background: var(--tempest-success-bg);\n color: var(--tempest-success-fg);\n}\n\n.tag.warning {\n background: var(--tempest-warning-bg);\n color: var(--tempest-warning-fg);\n}\n\n.tag.danger {\n background: var(--tempest-danger-bg);\n color: var(--tempest-danger-fg);\n}\n\n.tag.info {\n background: var(--tempest-info-bg);\n color: var(--tempest-info-fg);\n}\n\n.label {\n line-height: 1.2;\n}\n\n.remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: 0;\n color: currentColor;\n cursor: pointer;\n padding: 0;\n width: 16px;\n height: 16px;\n border-radius: var(--tempest-radius-full);\n font-size: 14px;\n line-height: 1;\n}\n\n.remove:hover {\n background: color-mix(in srgb, currentColor 15%, transparent);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Timeline.module.cjs","names":[],"sources":["../../../src/components/Timeline/Timeline.module.css"],"sourcesContent":[".timeline {\n list-style: none;\n margin: 0;\n padding: 0;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.item {\n display: flex;\n gap: var(--tempest-space-3);\n padding-bottom: var(--tempest-space-4);\n}\n\n.item:last-child {\n padding-bottom: 0;\n}\n\n.markerColumn {\n flex: 0 0 auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 16px;\n padding-top: 4px;\n}\n\n.marker {\n width: 14px;\n height: 14px;\n border-radius: var(--tempest-radius-full);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 10px;\n flex: 0 0 auto;\n}\n\n.marker-primary {\n background: var(--tempest-primary-solid, var(--tempest-primary));\n}\n.marker-success {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n.marker-warning {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n.marker-danger {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n.marker-neutral {\n background: var(--tempest-gray-400, var(--tempest-border));\n}\n\n.line {\n flex: 1 1 auto;\n width: 2px;\n background: var(--tempest-border);\n margin-top: 4px;\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--tempest-space-3);\n}\n\n.title {\n font-weight: var(--tempest-weight-medium);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.meta {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n white-space: nowrap;\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Timeline.module.cjs","names":[],"sources":["../../../src/components/Timeline/Timeline.module.css"],"sourcesContent":[".timeline {\n list-style: none;\n margin: 0;\n padding: 0;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.item {\n display: flex;\n gap: var(--tempest-space-3);\n padding-bottom: var(--tempest-space-4);\n}\n\n.item:last-child {\n padding-bottom: 0;\n}\n\n.markerColumn {\n flex: 0 0 auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 16px;\n padding-top: 4px;\n}\n\n.marker {\n width: 14px;\n height: 14px;\n border-radius: var(--tempest-radius-full);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 10px;\n flex: 0 0 auto;\n}\n\n.marker-primary {\n background: var(--tempest-primary);\n}\n.marker-success {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n.marker-warning {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n.marker-danger {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n.marker-neutral {\n background: var(--tempest-gray-400, var(--tempest-border));\n}\n\n.line {\n flex: 1 1 auto;\n width: 2px;\n background: var(--tempest-border);\n margin-top: 4px;\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--tempest-space-3);\n}\n\n.title {\n font-weight: var(--tempest-weight-medium);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.meta {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n white-space: nowrap;\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Timeline.module.js","names":[],"sources":["../../../src/components/Timeline/Timeline.module.css"],"sourcesContent":[".timeline {\n list-style: none;\n margin: 0;\n padding: 0;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.item {\n display: flex;\n gap: var(--tempest-space-3);\n padding-bottom: var(--tempest-space-4);\n}\n\n.item:last-child {\n padding-bottom: 0;\n}\n\n.markerColumn {\n flex: 0 0 auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 16px;\n padding-top: 4px;\n}\n\n.marker {\n width: 14px;\n height: 14px;\n border-radius: var(--tempest-radius-full);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 10px;\n flex: 0 0 auto;\n}\n\n.marker-primary {\n background: var(--tempest-primary-solid, var(--tempest-primary));\n}\n.marker-success {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n.marker-warning {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n.marker-danger {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n.marker-neutral {\n background: var(--tempest-gray-400, var(--tempest-border));\n}\n\n.line {\n flex: 1 1 auto;\n width: 2px;\n background: var(--tempest-border);\n margin-top: 4px;\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--tempest-space-3);\n}\n\n.title {\n font-weight: var(--tempest-weight-medium);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.meta {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n white-space: nowrap;\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Timeline.module.js","names":[],"sources":["../../../src/components/Timeline/Timeline.module.css"],"sourcesContent":[".timeline {\n list-style: none;\n margin: 0;\n padding: 0;\n font-family: var(--tempest-font-sans);\n color: var(--tempest-text);\n}\n\n.item {\n display: flex;\n gap: var(--tempest-space-3);\n padding-bottom: var(--tempest-space-4);\n}\n\n.item:last-child {\n padding-bottom: 0;\n}\n\n.markerColumn {\n flex: 0 0 auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 16px;\n padding-top: 4px;\n}\n\n.marker {\n width: 14px;\n height: 14px;\n border-radius: var(--tempest-radius-full);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 10px;\n flex: 0 0 auto;\n}\n\n.marker-primary {\n background: var(--tempest-primary);\n}\n.marker-success {\n background: var(--tempest-success-solid, var(--tempest-success));\n}\n.marker-warning {\n background: var(--tempest-warning-solid, var(--tempest-warning));\n}\n.marker-danger {\n background: var(--tempest-danger-solid, var(--tempest-danger));\n}\n.marker-neutral {\n background: var(--tempest-gray-400, var(--tempest-border));\n}\n\n.line {\n flex: 1 1 auto;\n width: 2px;\n background: var(--tempest-border);\n margin-top: 4px;\n}\n\n.body {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--tempest-space-3);\n}\n\n.title {\n font-weight: var(--tempest-weight-medium);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n\n.meta {\n font-size: var(--tempest-text-xs);\n color: var(--tempest-text-muted);\n white-space: nowrap;\n}\n\n.description {\n margin: var(--tempest-space-1) 0 0;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-sm);\n line-height: var(--tempest-leading-snug);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Toggle.module.cjs","names":[],"sources":["../../../src/components/Toggle/Toggle.module.css"],"sourcesContent":[".toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n border: 1px solid transparent;\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .toggle:hover {\n background-color: var(--tempest-surface-hover, var(--tempest-primary-soft));\n }\n}\n\n.toggle:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: 2px;\n}\n\n.toggle:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.outline {\n background-color: transparent;\n border-color: var(--tempest-border);\n}\n\n.pressed {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n border-color: var(--tempest-primary-soft);\n}\n\n.outline.pressed {\n border-color: var(--tempest-primary);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .pressed:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n\n.sm {\n min-height: 1.75rem;\n padding: 0 var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.md {\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n font-size: var(--tempest-text-sm);\n}\n\n.lg {\n min-height: 2.75rem;\n padding: 0 var(--tempest-space-4);\n font-size: var(--tempest-text-base);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Toggle.module.cjs","names":[],"sources":["../../../src/components/Toggle/Toggle.module.css"],"sourcesContent":[".toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n border: 1px solid transparent;\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .toggle:hover {\n background-color: var(--tempest-surface-2);\n }\n}\n\n.toggle:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: 2px;\n}\n\n.toggle:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.outline {\n background-color: transparent;\n border-color: var(--tempest-border);\n}\n\n.pressed {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n border-color: var(--tempest-primary-soft);\n}\n\n.outline.pressed {\n border-color: var(--tempest-primary);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .pressed:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n\n.sm {\n min-height: 1.75rem;\n padding: 0 var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.md {\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n font-size: var(--tempest-text-sm);\n}\n\n.lg {\n min-height: 2.75rem;\n padding: 0 var(--tempest-space-4);\n font-size: var(--tempest-text-base);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Toggle.module.js","names":[],"sources":["../../../src/components/Toggle/Toggle.module.css"],"sourcesContent":[".toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n border: 1px solid transparent;\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .toggle:hover {\n background-color: var(--tempest-surface-hover, var(--tempest-primary-soft));\n }\n}\n\n.toggle:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: 2px;\n}\n\n.toggle:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.outline {\n background-color: transparent;\n border-color: var(--tempest-border);\n}\n\n.pressed {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n border-color: var(--tempest-primary-soft);\n}\n\n.outline.pressed {\n border-color: var(--tempest-primary);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .pressed:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n\n.sm {\n min-height: 1.75rem;\n padding: 0 var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.md {\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n font-size: var(--tempest-text-sm);\n}\n\n.lg {\n min-height: 2.75rem;\n padding: 0 var(--tempest-space-4);\n font-size: var(--tempest-text-base);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Toggle.module.js","names":[],"sources":["../../../src/components/Toggle/Toggle.module.css"],"sourcesContent":[".toggle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n border: 1px solid transparent;\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .toggle:hover {\n background-color: var(--tempest-surface-2);\n }\n}\n\n.toggle:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: 2px;\n}\n\n.toggle:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.outline {\n background-color: transparent;\n border-color: var(--tempest-border);\n}\n\n.pressed {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n border-color: var(--tempest-primary-soft);\n}\n\n.outline.pressed {\n border-color: var(--tempest-primary);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .pressed:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n\n.sm {\n min-height: 1.75rem;\n padding: 0 var(--tempest-space-2);\n font-size: var(--tempest-text-xs);\n}\n\n.md {\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n font-size: var(--tempest-text-sm);\n}\n\n.lg {\n min-height: 2.75rem;\n padding: 0 var(--tempest-space-4);\n font-size: var(--tempest-text-base);\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ToggleGroup.module.cjs","names":[],"sources":["../../../src/components/ToggleGroup/ToggleGroup.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n overflow: hidden;\n}\n\n.item {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n border: none;\n border-left: 1px solid var(--tempest-border);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n.item:first-child {\n border-left: none;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .item:hover {\n background-color: var(--tempest-surface-hover, var(--tempest-primary-soft));\n }\n}\n\n.item:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: -2px;\n z-index: 1;\n}\n\n.item:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.selected {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .selected:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"ToggleGroup.module.cjs","names":[],"sources":["../../../src/components/ToggleGroup/ToggleGroup.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n overflow: hidden;\n}\n\n.item {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n border: none;\n border-left: 1px solid var(--tempest-border);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n.item:first-child {\n border-left: none;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .item:hover {\n background-color: var(--tempest-surface-2);\n }\n}\n\n.item:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: -2px;\n z-index: 1;\n}\n\n.item:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.selected {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .selected:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ToggleGroup.module.js","names":[],"sources":["../../../src/components/ToggleGroup/ToggleGroup.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n overflow: hidden;\n}\n\n.item {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n border: none;\n border-left: 1px solid var(--tempest-border);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n.item:first-child {\n border-left: none;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .item:hover {\n background-color: var(--tempest-surface-hover, var(--tempest-primary-soft));\n }\n}\n\n.item:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: -2px;\n z-index: 1;\n}\n\n.item:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.selected {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .selected:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"ToggleGroup.module.js","names":[],"sources":["../../../src/components/ToggleGroup/ToggleGroup.module.css"],"sourcesContent":[".group {\n display: inline-flex;\n align-items: stretch;\n gap: 0;\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n overflow: hidden;\n}\n\n.item {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--tempest-space-2);\n min-height: 2.25rem;\n padding: 0 var(--tempest-space-3);\n border: none;\n border-left: 1px solid var(--tempest-border);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n font-weight: var(--tempest-weight-medium);\n line-height: var(--tempest-leading-snug);\n cursor: pointer;\n transition:\n var(--tempest-transition-color),\n background-color var(--tempest-duration-base) var(--tempest-ease-emphasized);\n white-space: nowrap;\n}\n\n.item:first-child {\n border-left: none;\n}\n\n@media (hover: hover) and (pointer: fine) {\n .item:hover {\n background-color: var(--tempest-surface-2);\n }\n}\n\n.item:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: -2px;\n z-index: 1;\n}\n\n.item:disabled {\n opacity: 0.55;\n cursor: not-allowed;\n}\n\n.selected {\n background-color: var(--tempest-primary-soft);\n color: var(--tempest-primary-on-soft);\n}\n\n@media (hover: hover) and (pointer: fine) {\n .selected:hover {\n background-color: var(--tempest-primary-soft-hover, var(--tempest-primary-soft));\n }\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- const e=require("../../utils/cn.cjs"),t=require("../../hooks/use-fullscreen.cjs"),n=require("../../hooks/use-object-url.cjs"),r=require("./playback-rates.cjs"),i=require("../../audio/duration.cjs"),a=require("./VideoPlayer.module.cjs");let o=require("react"),s=require("react/jsx-runtime"),c=require("lucide-react");var l={"pt-BR":{play:`Tocar`,pause:`Pausar`,seek:`Posição`,mute:`Silenciar`,unmute:`Ativar som`,volume:`Volume`,rate:`Velocidade`,enterFullscreen:`Tela cheia`,exitFullscreen:`Sair da tela cheia`},en:{play:`Play`,pause:`Pause`,seek:`Seek`,mute:`Mute`,unmute:`Unmute`,volume:`Volume`,rate:`Speed`,enterFullscreen:`Full screen`,exitFullscreen:`Exit full screen`}};function u(e,t){return`${e.toLocaleString(t===`en`?`en-US`:`pt-BR`)}×`}function d({src:d,durationMs:f,poster:p,tracks:m,aspectRatio:h=16/9,rate:g,rates:_=r.DEFAULT_PLAYBACK_RATES,onRateChange:v,shiftPitch:y=!1,fullscreen:b=!0,autoPlay:x=!1,loop:S=!1,muted:C=!1,locale:w=`pt-BR`,actions:T,onEnded:E,onError:D,disabled:O=!1,className:k,...A}){let j=l[w],M=(0,o.useRef)(null),N=(0,o.useRef)(null),P=(0,o.useRef)(!1),[F,I]=(0,o.useState)(!1),[L,R]=(0,o.useState)(0),[z,B]=(0,o.useState)(1/0),[V,H]=(0,o.useState)(g??1),[U,W]=(0,o.useState)(1),[G,K]=(0,o.useState)(C),q=t.useFullscreen(M),J=n.useObjectUrl(typeof d==`string`?null:d),Y=typeof d==`string`?d:J,X=g??V,Z=Number.isFinite(f)?f:z,Q=Number.isFinite(Z)&&Z>0;(0,o.useEffect)(()=>{R(0),I(!1),B(1/0),P.current=!1},[Y]),(0,o.useEffect)(()=>{let e=N.current;e&&(e.defaultPlaybackRate=X,e.playbackRate=X,e.preservesPitch=!y)},[X,y,Y]),(0,o.useEffect)(()=>{let e=N.current;e&&(e.volume=U,e.muted=G)},[U,G,Y]);let $=()=>{let e=N.current;if(!e)return;if(Number.isFinite(e.duration)){B(e.duration*1e3);return}if(P.current||Number.isFinite(f))return;P.current=!0;let t=()=>{e.removeEventListener(`timeupdate`,t),Number.isFinite(e.duration)&&B(e.duration*1e3),e.currentTime=0};e.addEventListener(`timeupdate`,t),e.currentTime=1e101},ee=()=>{let e=N.current;if(!(!e||!Y)){if(e.paused){Promise.resolve(e.play()).then(()=>I(!0)).catch(e=>D?.(e));return}e.pause(),I(!1)}},te=e=>{let t=N.current;!t||!Q||(t.currentTime=e/1e3,R(e))},ne=e=>{g===void 0&&H(e),v?.(e)};return(0,s.jsxs)(`div`,{ref:M,className:e.cn(a.default.player,q.isFullscreen&&a.default.immersive,k),...A,children:[(0,s.jsx)(`div`,{className:a.default.frame,style:{aspectRatio:h},children:(0,s.jsx)(`video`,{ref:N,className:a.default.video,src:Y??void 0,poster:p,loop:S,autoPlay:x,playsInline:!0,preload:`metadata`,onLoadedMetadata:$,onDurationChange:$,onTimeUpdate:()=>{let e=N.current;e&&R(e.currentTime*1e3)},onPlay:()=>I(!0),onPause:()=>I(!1),onVolumeChange:()=>{let e=N.current;e&&(W(e.volume),K(e.muted))},onEnded:()=>{I(!1),E?.()},onError:e=>D?.(e),children:m?.map(e=>(0,s.jsx)(`track`,{kind:e.kind??`captions`,src:e.src,srcLang:e.srcLang,label:e.label,default:e.default},`${e.kind??`captions`}-${e.srcLang}-${e.src}`))})}),(0,s.jsxs)(`div`,{className:a.default.chrome,children:[(0,s.jsx)(`button`,{type:`button`,className:a.default.transport,onClick:ee,disabled:O||!Y,"aria-label":F?j.pause:j.play,title:F?j.pause:j.play,children:F?(0,s.jsx)(c.Pause,{size:16,"aria-hidden":!0}):(0,s.jsx)(c.Play,{size:16,"aria-hidden":!0})}),(0,s.jsx)(`input`,{type:`range`,className:a.default.seek,min:0,max:Q?Math.round(Z):0,step:100,value:Math.min(Math.round(L),Q?Math.round(Z):0),onChange:e=>te(Number(e.target.value)),disabled:O||!Q,"aria-label":j.seek,"aria-valuetext":`${i.formatDuration(L)} / ${i.formatDuration(Z)}`}),(0,s.jsxs)(`span`,{className:a.default.time,children:[(0,s.jsx)(`span`,{children:i.formatDuration(L)}),(0,s.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,s.jsx)(`span`,{children:i.formatDuration(Z)})]}),(0,s.jsx)(`button`,{type:`button`,className:a.default.icon,onClick:()=>K(e=>!e),disabled:O,"aria-label":G?j.unmute:j.mute,title:G?j.unmute:j.mute,children:G?(0,s.jsx)(c.VolumeX,{size:16,"aria-hidden":!0}):(0,s.jsx)(c.Volume2,{size:16,"aria-hidden":!0})}),(0,s.jsx)(`input`,{type:`range`,className:a.default.volume,min:0,max:1,step:.05,value:G?0:U,onChange:e=>{let t=Number(e.target.value);W(t),K(t===0)},disabled:O,"aria-label":j.volume}),_.length>0&&(0,s.jsx)(`select`,{className:a.default.rate,value:X,onChange:e=>ne(Number(e.target.value)),disabled:O,"aria-label":j.rate,title:j.rate,children:_.map(e=>(0,s.jsx)(`option`,{value:e,children:u(e,w)},e))}),b&&q.supported&&(0,s.jsx)(`button`,{type:`button`,className:a.default.icon,onClick:()=>{q.toggle().catch(e=>D?.(e))},disabled:O,"aria-label":q.isFullscreen?j.exitFullscreen:j.enterFullscreen,title:q.isFullscreen?j.exitFullscreen:j.enterFullscreen,children:q.isFullscreen?(0,s.jsx)(c.Minimize,{size:16,"aria-hidden":!0}):(0,s.jsx)(c.Maximize,{size:16,"aria-hidden":!0})}),T&&(0,s.jsx)(`span`,{className:a.default.actions,children:T})]})]})}exports.VideoPlayer=d;
1
+ const e=require("../../utils/cn.cjs"),t=require("../../hooks/use-fullscreen.cjs"),n=require("../../hooks/use-object-url.cjs"),r=require("./playback-rates.cjs"),i=require("../../audio/duration.cjs"),a=require("./VideoPlayer.module.cjs");let o=require("react"),s=require("react/jsx-runtime"),c=require("lucide-react");var l={"pt-BR":{play:`Tocar`,pause:`Pausar`,seek:`Posição`,mute:`Silenciar`,unmute:`Ativar som`,volume:`Volume`,rate:`Velocidade`,enterFullscreen:`Tela cheia`,exitFullscreen:`Sair da tela cheia`},en:{play:`Play`,pause:`Pause`,seek:`Seek`,mute:`Mute`,unmute:`Unmute`,volume:`Volume`,rate:`Speed`,enterFullscreen:`Full screen`,exitFullscreen:`Exit full screen`}};function u(e,t){return`${e.toLocaleString(t===`en`?`en-US`:`pt-BR`)}×`}function d({src:d,durationMs:f,poster:p,tracks:m,aspectRatio:h=16/9,rate:g,rates:_=r.DEFAULT_PLAYBACK_RATES,onRateChange:v,shiftPitch:y=!1,fullscreen:b=!0,autoPlay:x=!1,loop:S=!1,muted:C=!1,locale:w=`pt-BR`,actions:T,onEnded:E,onError:D,disabled:O=!1,className:k,...A}){let j=l[w],M=(0,o.useRef)(null),N=(0,o.useRef)(null),P=(0,o.useRef)(!1),[F,I]=(0,o.useState)(!1),[L,R]=(0,o.useState)(0),[z,B]=(0,o.useState)(1/0),[V,H]=(0,o.useState)(g??1),[U,W]=(0,o.useState)(1),[G,K]=(0,o.useState)(C),q=t.useFullscreen(M),J=n.useObjectUrl(typeof d==`string`?null:d),Y=typeof d==`string`?d:J,X=g??V,Z=Number.isFinite(f)?f:z,Q=Number.isFinite(Z)&&Z>0;(0,o.useEffect)(()=>{R(0),I(!1),B(1/0),P.current=!1},[Y]),(0,o.useEffect)(()=>{let e=N.current;e&&(e.defaultPlaybackRate=X,e.playbackRate=X,e.preservesPitch=!y)},[X,y,Y]),(0,o.useEffect)(()=>{let e=N.current;e&&(e.volume=U,e.muted=G)},[U,G,Y]);let $=()=>{let e=N.current;if(!e)return;if(Number.isFinite(e.duration)){B(e.duration*1e3);return}if(P.current||Number.isFinite(f))return;P.current=!0;let t=()=>{e.removeEventListener(`timeupdate`,t),Number.isFinite(e.duration)&&B(e.duration*1e3),e.currentTime=0};e.addEventListener(`timeupdate`,t),e.currentTime=1e101},ee=()=>{let e=N.current;if(e&&Y){if(e.paused){Promise.resolve(e.play()).then(()=>I(!0)).catch(e=>D?.(e));return}e.pause(),I(!1)}},te=e=>{let t=N.current;t&&Q&&(t.currentTime=e/1e3,R(e))},ne=e=>{g===void 0&&H(e),v?.(e)};return(0,s.jsxs)(`div`,{ref:M,className:e.cn(a.default.player,q.isFullscreen&&a.default.immersive,k),...A,children:[(0,s.jsx)(`div`,{className:a.default.frame,style:{aspectRatio:h},children:(0,s.jsx)(`video`,{ref:N,className:a.default.video,src:Y??void 0,poster:p,loop:S,autoPlay:x,playsInline:!0,preload:`metadata`,onLoadedMetadata:$,onDurationChange:$,onTimeUpdate:()=>{let e=N.current;e&&R(e.currentTime*1e3)},onPlay:()=>I(!0),onPause:()=>I(!1),onVolumeChange:()=>{let e=N.current;e&&(W(e.volume),K(e.muted))},onEnded:()=>{I(!1),E?.()},onError:e=>D?.(e),children:m?.map(e=>(0,s.jsx)(`track`,{kind:e.kind??`captions`,src:e.src,srcLang:e.srcLang,label:e.label,default:e.default},`${e.kind??`captions`}-${e.srcLang}-${e.src}`))})}),(0,s.jsxs)(`div`,{className:a.default.chrome,children:[(0,s.jsx)(`button`,{type:`button`,className:a.default.transport,onClick:ee,disabled:O||!Y,"aria-label":F?j.pause:j.play,title:F?j.pause:j.play,children:F?(0,s.jsx)(c.Pause,{size:16,"aria-hidden":!0}):(0,s.jsx)(c.Play,{size:16,"aria-hidden":!0})}),(0,s.jsx)(`input`,{type:`range`,className:a.default.seek,min:0,max:Q?Math.round(Z):0,step:100,value:Math.min(Math.round(L),Q?Math.round(Z):0),onChange:e=>te(Number(e.target.value)),disabled:O||!Q,"aria-label":j.seek,"aria-valuetext":`${i.formatDuration(L)} / ${i.formatDuration(Z)}`}),(0,s.jsxs)(`span`,{className:a.default.time,children:[(0,s.jsx)(`span`,{children:i.formatDuration(L)}),(0,s.jsx)(`span`,{"aria-hidden":`true`,children:`/`}),(0,s.jsx)(`span`,{children:i.formatDuration(Z)})]}),(0,s.jsx)(`button`,{type:`button`,className:a.default.icon,onClick:()=>K(e=>!e),disabled:O,"aria-label":G?j.unmute:j.mute,title:G?j.unmute:j.mute,children:G?(0,s.jsx)(c.VolumeX,{size:16,"aria-hidden":!0}):(0,s.jsx)(c.Volume2,{size:16,"aria-hidden":!0})}),(0,s.jsx)(`input`,{type:`range`,className:a.default.volume,min:0,max:1,step:.05,value:G?0:U,onChange:e=>{let t=Number(e.target.value);W(t),K(t===0)},disabled:O,"aria-label":j.volume}),_.length>0&&(0,s.jsx)(`select`,{className:a.default.rate,value:X,onChange:e=>ne(Number(e.target.value)),disabled:O,"aria-label":j.rate,title:j.rate,children:_.map(e=>(0,s.jsx)(`option`,{value:e,children:u(e,w)},e))}),b&&q.supported&&(0,s.jsx)(`button`,{type:`button`,className:a.default.icon,onClick:()=>{q.toggle().catch(e=>D?.(e))},disabled:O,"aria-label":q.isFullscreen?j.exitFullscreen:j.enterFullscreen,title:q.isFullscreen?j.exitFullscreen:j.enterFullscreen,children:q.isFullscreen?(0,s.jsx)(c.Minimize,{size:16,"aria-hidden":!0}):(0,s.jsx)(c.Maximize,{size:16,"aria-hidden":!0})}),T&&(0,s.jsx)(`span`,{className:a.default.actions,children:T})]})]})}exports.VideoPlayer=d;
2
2
  //# sourceMappingURL=VideoPlayer.cjs.map