tempest-react-sdk 0.77.0 → 0.79.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 (1623) hide show
  1. package/README.md +6 -6
  2. package/bin/lib/alias/collect.mjs +20 -3
  3. package/bin/lib/alias/index.mjs +12 -1
  4. package/bin/lib/alias/index.test.mjs +24 -0
  5. package/bin/lib/css/analyze.test.mjs +21 -1
  6. package/bin/lib/css/collect.mjs +14 -0
  7. package/bin/lib/css/extract.mjs +63 -5
  8. package/bin/lib/css/extract.test.mjs +110 -1
  9. package/bin/lib/css/fix.e2e.test.mjs +50 -0
  10. package/bin/lib/css/index.mjs +6 -1
  11. package/bin/lib/fs/contain.mjs +50 -0
  12. package/bin/lib/icons/generate.mjs +28 -3
  13. package/bin/lib/icons/generate.test.mjs +57 -1
  14. package/bin/lib/openapi/escape.mjs +20 -6
  15. package/bin/lib/openapi/generate.encode.test.mjs +120 -0
  16. package/bin/lib/openapi/generate.hostile.test.mjs +38 -9
  17. package/bin/lib/openapi/generate.mjs +203 -64
  18. package/bin/lib/openapi/generate.pagination.test.mjs +3 -2
  19. package/bin/lib/openapi/generate.test.mjs +270 -3
  20. package/bin/lib/openapi/schema-to-zod.mjs +5 -3
  21. package/bin/tempest-gen.test.mjs +188 -0
  22. package/bin/tempest.mjs +120 -44
  23. package/dist/access/Can.cjs.map +1 -1
  24. package/dist/access/Can.js.map +1 -1
  25. package/dist/access/access-control-context.cjs.map +1 -1
  26. package/dist/access/access-control-context.js.map +1 -1
  27. package/dist/access/create-role-access-control.cjs.map +1 -1
  28. package/dist/access/create-role-access-control.js.map +1 -1
  29. package/dist/access/permissions-from-token.cjs.map +1 -1
  30. package/dist/access/permissions-from-token.js.map +1 -1
  31. package/dist/access/use-can.cjs.map +1 -1
  32. package/dist/access/use-can.js.map +1 -1
  33. package/dist/app/AppProviders.cjs.map +1 -1
  34. package/dist/app/AppProviders.js.map +1 -1
  35. package/dist/audio/audio-bus.cjs.map +1 -1
  36. package/dist/audio/audio-bus.js.map +1 -1
  37. package/dist/audio/audio-output.cjs.map +1 -1
  38. package/dist/audio/audio-output.js.map +1 -1
  39. package/dist/audio/audio-player.cjs.map +1 -1
  40. package/dist/audio/audio-player.js.map +1 -1
  41. package/dist/audio/audio-recorder.cjs.map +1 -1
  42. package/dist/audio/audio-recorder.js.map +1 -1
  43. package/dist/audio/duration.cjs.map +1 -1
  44. package/dist/audio/duration.js.map +1 -1
  45. package/dist/audio/level-meter.cjs.map +1 -1
  46. package/dist/audio/level-meter.js.map +1 -1
  47. package/dist/audio/media-access.cjs.map +1 -1
  48. package/dist/audio/media-access.js.map +1 -1
  49. package/dist/audio/noise-floor.cjs.map +1 -1
  50. package/dist/audio/noise-floor.js.map +1 -1
  51. package/dist/audio/sfx-pool.cjs.map +1 -1
  52. package/dist/audio/sfx-pool.js.map +1 -1
  53. package/dist/audio/use-audio-bus.cjs.map +1 -1
  54. package/dist/audio/use-audio-bus.js.map +1 -1
  55. package/dist/audio/use-audio-recorder.cjs.map +1 -1
  56. package/dist/audio/use-audio-recorder.js.map +1 -1
  57. package/dist/audio/use-audio.cjs.map +1 -1
  58. package/dist/audio/use-audio.js.map +1 -1
  59. package/dist/audio/use-microphone.cjs +1 -1
  60. package/dist/audio/use-microphone.cjs.map +1 -1
  61. package/dist/audio/use-microphone.js +1 -5
  62. package/dist/audio/use-microphone.js.map +1 -1
  63. package/dist/audio/use-sfx-pool.cjs.map +1 -1
  64. package/dist/audio/use-sfx-pool.js.map +1 -1
  65. package/dist/audio/voice-activity.cjs.map +1 -1
  66. package/dist/audio/voice-activity.js.map +1 -1
  67. package/dist/audio/voice-chain-stages.cjs.map +1 -1
  68. package/dist/audio/voice-chain-stages.js.map +1 -1
  69. package/dist/audio/voice-chain.cjs.map +1 -1
  70. package/dist/audio/voice-chain.js.map +1 -1
  71. package/dist/audio/wav.cjs.map +1 -1
  72. package/dist/audio/wav.js.map +1 -1
  73. package/dist/auth/AuthGuard.cjs.map +1 -1
  74. package/dist/auth/AuthGuard.js.map +1 -1
  75. package/dist/auth/create-auth-store.cjs.map +1 -1
  76. package/dist/auth/create-auth-store.js.map +1 -1
  77. package/dist/auth/create-tempest-auth.cjs +1 -1
  78. package/dist/auth/create-tempest-auth.cjs.map +1 -1
  79. package/dist/auth/create-tempest-auth.js +185 -114
  80. package/dist/auth/create-tempest-auth.js.map +1 -1
  81. package/dist/auth/jwt.cjs.map +1 -1
  82. package/dist/auth/jwt.js.map +1 -1
  83. package/dist/auth/lazy-with-retry.cjs.map +1 -1
  84. package/dist/auth/lazy-with-retry.js.map +1 -1
  85. package/dist/auth/passkey.cjs.map +1 -1
  86. package/dist/auth/passkey.js.map +1 -1
  87. package/dist/auth/refresh-queue.cjs.map +1 -1
  88. package/dist/auth/refresh-queue.js.map +1 -1
  89. package/dist/auth/use-passkey.cjs +1 -1
  90. package/dist/auth/use-passkey.cjs.map +1 -1
  91. package/dist/auth/use-passkey.js +1 -1
  92. package/dist/auth/use-passkey.js.map +1 -1
  93. package/dist/br/BrazilMap.cjs.map +1 -1
  94. package/dist/br/BrazilMap.js.map +1 -1
  95. package/dist/br/BrazilMap.module.cjs.map +1 -1
  96. package/dist/br/BrazilMap.module.js.map +1 -1
  97. package/dist/br/BrazilStateCitySelect.cjs.map +1 -1
  98. package/dist/br/BrazilStateCitySelect.js.map +1 -1
  99. package/dist/br/BrazilStateMap.cjs.map +1 -1
  100. package/dist/br/BrazilStateMap.js.map +1 -1
  101. package/dist/br/MapLegend.cjs.map +1 -1
  102. package/dist/br/MapLegend.js.map +1 -1
  103. package/dist/br/MapLegend.module.cjs.map +1 -1
  104. package/dist/br/MapLegend.module.js.map +1 -1
  105. package/dist/br/MapMarkers.cjs.map +1 -1
  106. package/dist/br/MapMarkers.js.map +1 -1
  107. package/dist/br/MapTooltip.cjs.map +1 -1
  108. package/dist/br/MapTooltip.js.map +1 -1
  109. package/dist/br/MunicipalitySearch.cjs +1 -1
  110. package/dist/br/MunicipalitySearch.cjs.map +1 -1
  111. package/dist/br/MunicipalitySearch.js +2 -5
  112. package/dist/br/MunicipalitySearch.js.map +1 -1
  113. package/dist/br/MunicipalitySearch.module.cjs.map +1 -1
  114. package/dist/br/MunicipalitySearch.module.js.map +1 -1
  115. package/dist/br/PixQRCode.cjs.map +1 -1
  116. package/dist/br/PixQRCode.js.map +1 -1
  117. package/dist/br/PixQRCode.module.cjs.map +1 -1
  118. package/dist/br/PixQRCode.module.js.map +1 -1
  119. package/dist/br/boleto.cjs.map +1 -1
  120. package/dist/br/boleto.js.map +1 -1
  121. package/dist/br/br-geo.cjs.map +1 -1
  122. package/dist/br/br-geo.js.map +1 -1
  123. package/dist/br/data/br-centroids.cjs.map +1 -1
  124. package/dist/br/data/br-centroids.js.map +1 -1
  125. package/dist/br/data/br-locations.cjs.map +1 -1
  126. package/dist/br/data/br-locations.js.map +1 -1
  127. package/dist/br/data/br-uf-geo.cjs.map +1 -1
  128. package/dist/br/data/br-uf-geo.js.map +1 -1
  129. package/dist/br/data/mun/AC.cjs.map +1 -1
  130. package/dist/br/data/mun/AC.js.map +1 -1
  131. package/dist/br/data/mun/AL.cjs.map +1 -1
  132. package/dist/br/data/mun/AL.js.map +1 -1
  133. package/dist/br/data/mun/AM.cjs.map +1 -1
  134. package/dist/br/data/mun/AM.js.map +1 -1
  135. package/dist/br/data/mun/AP.cjs.map +1 -1
  136. package/dist/br/data/mun/AP.js.map +1 -1
  137. package/dist/br/data/mun/BA.cjs.map +1 -1
  138. package/dist/br/data/mun/BA.js.map +1 -1
  139. package/dist/br/data/mun/CE.cjs.map +1 -1
  140. package/dist/br/data/mun/CE.js.map +1 -1
  141. package/dist/br/data/mun/DF.cjs.map +1 -1
  142. package/dist/br/data/mun/DF.js.map +1 -1
  143. package/dist/br/data/mun/ES.cjs.map +1 -1
  144. package/dist/br/data/mun/ES.js.map +1 -1
  145. package/dist/br/data/mun/GO.cjs.map +1 -1
  146. package/dist/br/data/mun/GO.js.map +1 -1
  147. package/dist/br/data/mun/MA.cjs.map +1 -1
  148. package/dist/br/data/mun/MA.js.map +1 -1
  149. package/dist/br/data/mun/MG.cjs.map +1 -1
  150. package/dist/br/data/mun/MG.js.map +1 -1
  151. package/dist/br/data/mun/MS.cjs.map +1 -1
  152. package/dist/br/data/mun/MS.js.map +1 -1
  153. package/dist/br/data/mun/MT.cjs.map +1 -1
  154. package/dist/br/data/mun/MT.js.map +1 -1
  155. package/dist/br/data/mun/PA.cjs.map +1 -1
  156. package/dist/br/data/mun/PA.js.map +1 -1
  157. package/dist/br/data/mun/PB.cjs.map +1 -1
  158. package/dist/br/data/mun/PB.js.map +1 -1
  159. package/dist/br/data/mun/PE.cjs.map +1 -1
  160. package/dist/br/data/mun/PE.js.map +1 -1
  161. package/dist/br/data/mun/PI.cjs.map +1 -1
  162. package/dist/br/data/mun/PI.js.map +1 -1
  163. package/dist/br/data/mun/PR.cjs.map +1 -1
  164. package/dist/br/data/mun/PR.js.map +1 -1
  165. package/dist/br/data/mun/RJ.cjs.map +1 -1
  166. package/dist/br/data/mun/RJ.js.map +1 -1
  167. package/dist/br/data/mun/RN.cjs.map +1 -1
  168. package/dist/br/data/mun/RN.js.map +1 -1
  169. package/dist/br/data/mun/RO.cjs.map +1 -1
  170. package/dist/br/data/mun/RO.js.map +1 -1
  171. package/dist/br/data/mun/RR.cjs.map +1 -1
  172. package/dist/br/data/mun/RR.js.map +1 -1
  173. package/dist/br/data/mun/RS.cjs.map +1 -1
  174. package/dist/br/data/mun/RS.js.map +1 -1
  175. package/dist/br/data/mun/SC.cjs.map +1 -1
  176. package/dist/br/data/mun/SC.js.map +1 -1
  177. package/dist/br/data/mun/SE.cjs.map +1 -1
  178. package/dist/br/data/mun/SE.js.map +1 -1
  179. package/dist/br/data/mun/SP.cjs.map +1 -1
  180. package/dist/br/data/mun/SP.js.map +1 -1
  181. package/dist/br/data/mun/TO.cjs.map +1 -1
  182. package/dist/br/data/mun/TO.js.map +1 -1
  183. package/dist/br/geocode.cjs.map +1 -1
  184. package/dist/br/geocode.js.map +1 -1
  185. package/dist/br/holidays.cjs.map +1 -1
  186. package/dist/br/holidays.js.map +1 -1
  187. package/dist/br/locations.cjs.map +1 -1
  188. package/dist/br/locations.js.map +1 -1
  189. package/dist/br/nfe.cjs.map +1 -1
  190. package/dist/br/nfe.js.map +1 -1
  191. package/dist/br/pix.cjs +1 -1
  192. package/dist/br/pix.cjs.map +1 -1
  193. package/dist/br/pix.js +108 -71
  194. package/dist/br/pix.js.map +1 -1
  195. package/dist/br/regions.cjs.map +1 -1
  196. package/dist/br/regions.js.map +1 -1
  197. package/dist/br/scales.cjs.map +1 -1
  198. package/dist/br/scales.js.map +1 -1
  199. package/dist/br/state-geo.cjs.map +1 -1
  200. package/dist/br/state-geo.js.map +1 -1
  201. package/dist/br/svg-utils.cjs.map +1 -1
  202. package/dist/br/svg-utils.js.map +1 -1
  203. package/dist/br/use-map-hover.cjs.map +1 -1
  204. package/dist/br/use-map-hover.js.map +1 -1
  205. package/dist/br/use-map-zoom.cjs.map +1 -1
  206. package/dist/br/use-map-zoom.js.map +1 -1
  207. package/dist/br/whatsapp.cjs.map +1 -1
  208. package/dist/br/whatsapp.js.map +1 -1
  209. package/dist/br.cjs.map +1 -1
  210. package/dist/br.d.ts +16 -5
  211. package/dist/br.js.map +1 -1
  212. package/dist/capture/barcode.cjs.map +1 -1
  213. package/dist/capture/barcode.js.map +1 -1
  214. package/dist/capture/media-recorder.cjs.map +1 -1
  215. package/dist/capture/media-recorder.js.map +1 -1
  216. package/dist/capture/use-barcode-scanner.cjs.map +1 -1
  217. package/dist/capture/use-barcode-scanner.js.map +1 -1
  218. package/dist/capture/use-screen-capture.cjs +1 -1
  219. package/dist/capture/use-screen-capture.cjs.map +1 -1
  220. package/dist/capture/use-screen-capture.js +1 -7
  221. package/dist/capture/use-screen-capture.js.map +1 -1
  222. package/dist/capture/use-speech-recognition.cjs +1 -1
  223. package/dist/capture/use-speech-recognition.cjs.map +1 -1
  224. package/dist/capture/use-speech-recognition.js +35 -36
  225. package/dist/capture/use-speech-recognition.js.map +1 -1
  226. package/dist/capture/use-torch.cjs.map +1 -1
  227. package/dist/capture/use-torch.js.map +1 -1
  228. package/dist/capture/use-video-recorder.cjs.map +1 -1
  229. package/dist/capture/use-video-recorder.js.map +1 -1
  230. package/dist/capture/video-recorder.cjs.map +1 -1
  231. package/dist/capture/video-recorder.js.map +1 -1
  232. package/dist/charts/AreaChart.cjs.map +1 -1
  233. package/dist/charts/AreaChart.js.map +1 -1
  234. package/dist/charts/BarChart.cjs.map +1 -1
  235. package/dist/charts/BarChart.js.map +1 -1
  236. package/dist/charts/LineChart.cjs.map +1 -1
  237. package/dist/charts/LineChart.js.map +1 -1
  238. package/dist/charts/PieChart.cjs.map +1 -1
  239. package/dist/charts/PieChart.js.map +1 -1
  240. package/dist/charts/RadarChart.cjs.map +1 -1
  241. package/dist/charts/RadarChart.js.map +1 -1
  242. package/dist/charts/palette.cjs.map +1 -1
  243. package/dist/charts/palette.js.map +1 -1
  244. package/dist/charts/scales.cjs.map +1 -1
  245. package/dist/charts/scales.js.map +1 -1
  246. package/dist/charts/types.cjs.map +1 -1
  247. package/dist/charts/types.js.map +1 -1
  248. package/dist/charts/use-chart-colors.cjs.map +1 -1
  249. package/dist/charts/use-chart-colors.js.map +1 -1
  250. package/dist/components/AIChat/AIChat.cjs +1 -1
  251. package/dist/components/AIChat/AIChat.cjs.map +1 -1
  252. package/dist/components/AIChat/AIChat.js +1 -5
  253. package/dist/components/AIChat/AIChat.js.map +1 -1
  254. package/dist/components/AIChat/AIChat.module.cjs.map +1 -1
  255. package/dist/components/AIChat/AIChat.module.js.map +1 -1
  256. package/dist/components/AIChat/AIChatComposer.cjs +1 -1
  257. package/dist/components/AIChat/AIChatComposer.cjs.map +1 -1
  258. package/dist/components/AIChat/AIChatComposer.js +1 -7
  259. package/dist/components/AIChat/AIChatComposer.js.map +1 -1
  260. package/dist/components/AIChat/AIChatTurn.cjs.map +1 -1
  261. package/dist/components/AIChat/AIChatTurn.js.map +1 -1
  262. package/dist/components/AIChat/ai-chat-turns.cjs.map +1 -1
  263. package/dist/components/AIChat/ai-chat-turns.js.map +1 -1
  264. package/dist/components/Accordion/Accordion.cjs.map +1 -1
  265. package/dist/components/Accordion/Accordion.js.map +1 -1
  266. package/dist/components/Accordion/Accordion.module.cjs.map +1 -1
  267. package/dist/components/Accordion/Accordion.module.js.map +1 -1
  268. package/dist/components/Alert/Alert.cjs.map +1 -1
  269. package/dist/components/Alert/Alert.js.map +1 -1
  270. package/dist/components/Alert/Alert.module.cjs.map +1 -1
  271. package/dist/components/Alert/Alert.module.js.map +1 -1
  272. package/dist/components/AppBar/AppBar.cjs.map +1 -1
  273. package/dist/components/AppBar/AppBar.js.map +1 -1
  274. package/dist/components/AppBar/AppBar.module.cjs.map +1 -1
  275. package/dist/components/AppBar/AppBar.module.js.map +1 -1
  276. package/dist/components/AppBar/use-sticky-body-warning.cjs +1 -1
  277. package/dist/components/AppBar/use-sticky-body-warning.cjs.map +1 -1
  278. package/dist/components/AppBar/use-sticky-body-warning.js +1 -1
  279. package/dist/components/AppBar/use-sticky-body-warning.js.map +1 -1
  280. package/dist/components/AppShell/AppShell.cjs.map +1 -1
  281. package/dist/components/AppShell/AppShell.js.map +1 -1
  282. package/dist/components/AppShell/AppShell.module.cjs.map +1 -1
  283. package/dist/components/AppShell/AppShell.module.js.map +1 -1
  284. package/dist/components/AspectRatio/AspectRatio.cjs.map +1 -1
  285. package/dist/components/AspectRatio/AspectRatio.js.map +1 -1
  286. package/dist/components/AspectRatio/AspectRatio.module.cjs.map +1 -1
  287. package/dist/components/AspectRatio/AspectRatio.module.js.map +1 -1
  288. package/dist/components/AudioPlayer/AudioPlayer.cjs +1 -1
  289. package/dist/components/AudioPlayer/AudioPlayer.cjs.map +1 -1
  290. package/dist/components/AudioPlayer/AudioPlayer.js +1 -7
  291. package/dist/components/AudioPlayer/AudioPlayer.js.map +1 -1
  292. package/dist/components/AudioPlayer/AudioPlayer.module.cjs.map +1 -1
  293. package/dist/components/AudioPlayer/AudioPlayer.module.js.map +1 -1
  294. package/dist/components/AudioRecorder/AudioRecorder.cjs +1 -1
  295. package/dist/components/AudioRecorder/AudioRecorder.cjs.map +1 -1
  296. package/dist/components/AudioRecorder/AudioRecorder.js +16 -21
  297. package/dist/components/AudioRecorder/AudioRecorder.js.map +1 -1
  298. package/dist/components/AudioRecorder/AudioRecorder.module.cjs.map +1 -1
  299. package/dist/components/AudioRecorder/AudioRecorder.module.js.map +1 -1
  300. package/dist/components/Avatar/Avatar.cjs.map +1 -1
  301. package/dist/components/Avatar/Avatar.js.map +1 -1
  302. package/dist/components/Avatar/Avatar.module.cjs.map +1 -1
  303. package/dist/components/Avatar/Avatar.module.js.map +1 -1
  304. package/dist/components/AvatarGroup/AvatarGroup.cjs.map +1 -1
  305. package/dist/components/AvatarGroup/AvatarGroup.js.map +1 -1
  306. package/dist/components/AvatarGroup/AvatarGroup.module.cjs.map +1 -1
  307. package/dist/components/AvatarGroup/AvatarGroup.module.js.map +1 -1
  308. package/dist/components/Badge/Badge.cjs.map +1 -1
  309. package/dist/components/Badge/Badge.js.map +1 -1
  310. package/dist/components/Badge/Badge.module.cjs.map +1 -1
  311. package/dist/components/Badge/Badge.module.js.map +1 -1
  312. package/dist/components/Banner/Banner.cjs.map +1 -1
  313. package/dist/components/Banner/Banner.js.map +1 -1
  314. package/dist/components/Banner/Banner.module.cjs.map +1 -1
  315. package/dist/components/Banner/Banner.module.js.map +1 -1
  316. package/dist/components/BarList/BarList.cjs.map +1 -1
  317. package/dist/components/BarList/BarList.js.map +1 -1
  318. package/dist/components/BarList/BarList.module.cjs.map +1 -1
  319. package/dist/components/BarList/BarList.module.js.map +1 -1
  320. package/dist/components/BarList/bar-list-model.cjs.map +1 -1
  321. package/dist/components/BarList/bar-list-model.js.map +1 -1
  322. package/dist/components/BarcodeScanner/BarcodeScanner.cjs.map +1 -1
  323. package/dist/components/BarcodeScanner/BarcodeScanner.js.map +1 -1
  324. package/dist/components/BarcodeScanner/BarcodeScanner.module.cjs.map +1 -1
  325. package/dist/components/BarcodeScanner/BarcodeScanner.module.js.map +1 -1
  326. package/dist/components/BottomNavigation/BottomNavigation.cjs.map +1 -1
  327. package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
  328. package/dist/components/BottomNavigation/BottomNavigation.module.cjs.map +1 -1
  329. package/dist/components/BottomNavigation/BottomNavigation.module.js.map +1 -1
  330. package/dist/components/BottomSheet/BottomSheet.cjs.map +1 -1
  331. package/dist/components/BottomSheet/BottomSheet.js.map +1 -1
  332. package/dist/components/BottomSheet/BottomSheet.module.cjs.map +1 -1
  333. package/dist/components/BottomSheet/BottomSheet.module.js.map +1 -1
  334. package/dist/components/Breadcrumbs/Breadcrumbs.cjs.map +1 -1
  335. package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -1
  336. package/dist/components/Breadcrumbs/Breadcrumbs.module.cjs.map +1 -1
  337. package/dist/components/Breadcrumbs/Breadcrumbs.module.js.map +1 -1
  338. package/dist/components/Button/Button.cjs.map +1 -1
  339. package/dist/components/Button/Button.js.map +1 -1
  340. package/dist/components/Button/Button.module.cjs.map +1 -1
  341. package/dist/components/Button/Button.module.js.map +1 -1
  342. package/dist/components/Button/ButtonContent.cjs.map +1 -1
  343. package/dist/components/Button/ButtonContent.js.map +1 -1
  344. package/dist/components/Button/ButtonSlot.cjs.map +1 -1
  345. package/dist/components/Button/ButtonSlot.js.map +1 -1
  346. package/dist/components/Button/button-class.cjs.map +1 -1
  347. package/dist/components/Button/button-class.js.map +1 -1
  348. package/dist/components/Button/link-rel.cjs.map +1 -1
  349. package/dist/components/Button/link-rel.js.map +1 -1
  350. package/dist/components/Button/slot.cjs.map +1 -1
  351. package/dist/components/Button/slot.js.map +1 -1
  352. package/dist/components/Calendar/Calendar.cjs.map +1 -1
  353. package/dist/components/Calendar/Calendar.js.map +1 -1
  354. package/dist/components/Calendar/Calendar.module.cjs.map +1 -1
  355. package/dist/components/Calendar/Calendar.module.js.map +1 -1
  356. package/dist/components/Card/Card.cjs.map +1 -1
  357. package/dist/components/Card/Card.js.map +1 -1
  358. package/dist/components/Card/Card.module.cjs.map +1 -1
  359. package/dist/components/Card/Card.module.js.map +1 -1
  360. package/dist/components/Carousel/Carousel.cjs.map +1 -1
  361. package/dist/components/Carousel/Carousel.js.map +1 -1
  362. package/dist/components/Carousel/Carousel.module.cjs.map +1 -1
  363. package/dist/components/Carousel/Carousel.module.js.map +1 -1
  364. package/dist/components/Center/Center.cjs.map +1 -1
  365. package/dist/components/Center/Center.js.map +1 -1
  366. package/dist/components/Center/Center.module.cjs.map +1 -1
  367. package/dist/components/Center/Center.module.js.map +1 -1
  368. package/dist/components/Chat/Chat.cjs.map +1 -1
  369. package/dist/components/Chat/Chat.js.map +1 -1
  370. package/dist/components/Chat/Chat.module.cjs.map +1 -1
  371. package/dist/components/Chat/Chat.module.js.map +1 -1
  372. package/dist/components/Chat/ChatActionsMenu.cjs.map +1 -1
  373. package/dist/components/Chat/ChatActionsMenu.js.map +1 -1
  374. package/dist/components/Chat/ChatAttachments.cjs.map +1 -1
  375. package/dist/components/Chat/ChatAttachments.js.map +1 -1
  376. package/dist/components/Chat/ChatBubble.cjs.map +1 -1
  377. package/dist/components/Chat/ChatBubble.js.map +1 -1
  378. package/dist/components/Chat/ChatComposer.cjs.map +1 -1
  379. package/dist/components/Chat/ChatComposer.js.map +1 -1
  380. package/dist/components/Chat/chat-groups.cjs +1 -1
  381. package/dist/components/Chat/chat-groups.cjs.map +1 -1
  382. package/dist/components/Chat/chat-groups.js +2 -6
  383. package/dist/components/Chat/chat-groups.js.map +1 -1
  384. package/dist/components/Chat/chat-receipt.cjs.map +1 -1
  385. package/dist/components/Chat/chat-receipt.js.map +1 -1
  386. package/dist/components/Checkbox/Checkbox.cjs.map +1 -1
  387. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  388. package/dist/components/Checkbox/Checkbox.module.cjs.map +1 -1
  389. package/dist/components/Checkbox/Checkbox.module.js.map +1 -1
  390. package/dist/components/ChipInput/ChipInput.cjs +1 -1
  391. package/dist/components/ChipInput/ChipInput.cjs.map +1 -1
  392. package/dist/components/ChipInput/ChipInput.js +2 -12
  393. package/dist/components/ChipInput/ChipInput.js.map +1 -1
  394. package/dist/components/ChipInput/ChipInput.module.cjs.map +1 -1
  395. package/dist/components/ChipInput/ChipInput.module.js.map +1 -1
  396. package/dist/components/ClickOutside/ClickOutside.cjs.map +1 -1
  397. package/dist/components/ClickOutside/ClickOutside.js.map +1 -1
  398. package/dist/components/CodeBlock/CodeBlock.cjs +1 -1
  399. package/dist/components/CodeBlock/CodeBlock.cjs.map +1 -1
  400. package/dist/components/CodeBlock/CodeBlock.js +1 -1
  401. package/dist/components/CodeBlock/CodeBlock.js.map +1 -1
  402. package/dist/components/CodeBlock/CodeBlock.module.cjs.map +1 -1
  403. package/dist/components/CodeBlock/CodeBlock.module.js.map +1 -1
  404. package/dist/components/CodeBlock/tokenize.cjs +1 -1
  405. package/dist/components/CodeBlock/tokenize.cjs.map +1 -1
  406. package/dist/components/CodeBlock/tokenize.js +54 -25
  407. package/dist/components/CodeBlock/tokenize.js.map +1 -1
  408. package/dist/components/Collapsible/Collapsible.cjs.map +1 -1
  409. package/dist/components/Collapsible/Collapsible.js.map +1 -1
  410. package/dist/components/Collapsible/Collapsible.module.cjs.map +1 -1
  411. package/dist/components/Collapsible/Collapsible.module.js.map +1 -1
  412. package/dist/components/Combobox/Combobox.cjs.map +1 -1
  413. package/dist/components/Combobox/Combobox.js.map +1 -1
  414. package/dist/components/Combobox/Combobox.module.cjs.map +1 -1
  415. package/dist/components/Combobox/Combobox.module.js.map +1 -1
  416. package/dist/components/Combobox/use-listbox-dismiss.cjs.map +1 -1
  417. package/dist/components/Combobox/use-listbox-dismiss.js.map +1 -1
  418. package/dist/components/Command/Command.cjs +1 -1
  419. package/dist/components/Command/Command.cjs.map +1 -1
  420. package/dist/components/Command/Command.js +4 -11
  421. package/dist/components/Command/Command.js.map +1 -1
  422. package/dist/components/Command/Command.module.cjs.map +1 -1
  423. package/dist/components/Command/Command.module.js.map +1 -1
  424. package/dist/components/ConditionalWrapper/ConditionalWrapper.cjs.map +1 -1
  425. package/dist/components/ConditionalWrapper/ConditionalWrapper.js.map +1 -1
  426. package/dist/components/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
  427. package/dist/components/ConfirmDialog/ConfirmDialog.js.map +1 -1
  428. package/dist/components/ContextMenu/ContextMenu.cjs +1 -1
  429. package/dist/components/ContextMenu/ContextMenu.cjs.map +1 -1
  430. package/dist/components/ContextMenu/ContextMenu.js +1 -1
  431. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  432. package/dist/components/ContextMenu/ContextMenu.module.cjs.map +1 -1
  433. package/dist/components/ContextMenu/ContextMenu.module.js.map +1 -1
  434. package/dist/components/CopyButton/CopyButton.cjs.map +1 -1
  435. package/dist/components/CopyButton/CopyButton.js.map +1 -1
  436. package/dist/components/CopyButton/CopyButton.module.cjs.map +1 -1
  437. package/dist/components/CopyButton/CopyButton.module.js.map +1 -1
  438. package/dist/components/DataList/DataList.cjs.map +1 -1
  439. package/dist/components/DataList/DataList.js.map +1 -1
  440. package/dist/components/DataList/DataList.module.cjs.map +1 -1
  441. package/dist/components/DataList/DataList.module.js.map +1 -1
  442. package/dist/components/DataTable/DataTable.cjs +1 -1
  443. package/dist/components/DataTable/DataTable.cjs.map +1 -1
  444. package/dist/components/DataTable/DataTable.js +6 -14
  445. package/dist/components/DataTable/DataTable.js.map +1 -1
  446. package/dist/components/DataTable/DataTable.module.cjs.map +1 -1
  447. package/dist/components/DataTable/DataTable.module.js.map +1 -1
  448. package/dist/components/DataTable/EditableCell.cjs +1 -1
  449. package/dist/components/DataTable/EditableCell.cjs.map +1 -1
  450. package/dist/components/DataTable/EditableCell.js +1 -9
  451. package/dist/components/DataTable/EditableCell.js.map +1 -1
  452. package/dist/components/DataTable/LoadingRows.cjs.map +1 -1
  453. package/dist/components/DataTable/LoadingRows.js.map +1 -1
  454. package/dist/components/DataTable/edit-labels.cjs.map +1 -1
  455. package/dist/components/DataTable/edit-labels.js.map +1 -1
  456. package/dist/components/DataTable/use-dev-warnings.cjs.map +1 -1
  457. package/dist/components/DataTable/use-dev-warnings.js.map +1 -1
  458. package/dist/components/DatePicker/DatePicker.cjs.map +1 -1
  459. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  460. package/dist/components/DateRangePicker/DateRangePicker.cjs.map +1 -1
  461. package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
  462. package/dist/components/DateRangePicker/DateRangePicker.module.cjs.map +1 -1
  463. package/dist/components/DateRangePicker/DateRangePicker.module.js.map +1 -1
  464. package/dist/components/DescriptionList/DescriptionList.cjs.map +1 -1
  465. package/dist/components/DescriptionList/DescriptionList.js.map +1 -1
  466. package/dist/components/DescriptionList/DescriptionList.module.cjs.map +1 -1
  467. package/dist/components/DescriptionList/DescriptionList.module.js.map +1 -1
  468. package/dist/components/Divider/Divider.cjs.map +1 -1
  469. package/dist/components/Divider/Divider.js.map +1 -1
  470. package/dist/components/Divider/Divider.module.cjs.map +1 -1
  471. package/dist/components/Divider/Divider.module.js.map +1 -1
  472. package/dist/components/Drawer/Drawer.cjs.map +1 -1
  473. package/dist/components/Drawer/Drawer.js.map +1 -1
  474. package/dist/components/Drawer/Drawer.module.cjs.map +1 -1
  475. package/dist/components/Drawer/Drawer.module.js.map +1 -1
  476. package/dist/components/DropdownMenu/DropdownMenu.cjs +1 -1
  477. package/dist/components/DropdownMenu/DropdownMenu.cjs.map +1 -1
  478. package/dist/components/DropdownMenu/DropdownMenu.js +2 -14
  479. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  480. package/dist/components/DropdownMenu/DropdownMenu.module.cjs.map +1 -1
  481. package/dist/components/DropdownMenu/DropdownMenu.module.js.map +1 -1
  482. package/dist/components/Dropzone/Dropzone.cjs.map +1 -1
  483. package/dist/components/Dropzone/Dropzone.js.map +1 -1
  484. package/dist/components/Dropzone/Dropzone.module.cjs.map +1 -1
  485. package/dist/components/Dropzone/Dropzone.module.js.map +1 -1
  486. package/dist/components/EmptyState/EmptyState.cjs.map +1 -1
  487. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  488. package/dist/components/EmptyState/EmptyState.module.cjs.map +1 -1
  489. package/dist/components/EmptyState/EmptyState.module.js.map +1 -1
  490. package/dist/components/ErrorState/ErrorState.cjs.map +1 -1
  491. package/dist/components/ErrorState/ErrorState.js.map +1 -1
  492. package/dist/components/ErrorState/ErrorState.module.cjs.map +1 -1
  493. package/dist/components/ErrorState/ErrorState.module.js.map +1 -1
  494. package/dist/components/ErrorText/ErrorText.cjs.map +1 -1
  495. package/dist/components/ErrorText/ErrorText.js.map +1 -1
  496. package/dist/components/ErrorText/ErrorText.module.cjs.map +1 -1
  497. package/dist/components/ErrorText/ErrorText.module.js.map +1 -1
  498. package/dist/components/FileUpload/FileUpload.cjs +1 -1
  499. package/dist/components/FileUpload/FileUpload.cjs.map +1 -1
  500. package/dist/components/FileUpload/FileUpload.js +7 -17
  501. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  502. package/dist/components/FileUpload/FileUpload.module.cjs.map +1 -1
  503. package/dist/components/FileUpload/FileUpload.module.js.map +1 -1
  504. package/dist/components/FilterBar/FilterBar.cjs.map +1 -1
  505. package/dist/components/FilterBar/FilterBar.js.map +1 -1
  506. package/dist/components/FilterBar/FilterBar.module.cjs.map +1 -1
  507. package/dist/components/FilterBar/FilterBar.module.js.map +1 -1
  508. package/dist/components/FilterBar/filter-apply.cjs.map +1 -1
  509. package/dist/components/FilterBar/filter-apply.js.map +1 -1
  510. package/dist/components/FilterBar/filter-model.cjs.map +1 -1
  511. package/dist/components/FilterBar/filter-model.js.map +1 -1
  512. package/dist/components/FilterBar/filter-query.cjs +1 -1
  513. package/dist/components/FilterBar/filter-query.cjs.map +1 -1
  514. package/dist/components/FilterBar/filter-query.js +2 -5
  515. package/dist/components/FilterBar/filter-query.js.map +1 -1
  516. package/dist/components/FilterPanel/FilterPanel.cjs.map +1 -1
  517. package/dist/components/FilterPanel/FilterPanel.js.map +1 -1
  518. package/dist/components/FilterPanel/FilterPanel.module.cjs.map +1 -1
  519. package/dist/components/FilterPanel/FilterPanel.module.js.map +1 -1
  520. package/dist/components/FloatingActionButton/FloatingActionButton.cjs.map +1 -1
  521. package/dist/components/FloatingActionButton/FloatingActionButton.js.map +1 -1
  522. package/dist/components/FloatingActionButton/FloatingActionButton.module.cjs.map +1 -1
  523. package/dist/components/FloatingActionButton/FloatingActionButton.module.js.map +1 -1
  524. package/dist/components/For/For.cjs.map +1 -1
  525. package/dist/components/For/For.js.map +1 -1
  526. package/dist/components/Form/Form.cjs.map +1 -1
  527. package/dist/components/Form/Form.js.map +1 -1
  528. package/dist/components/Form/Form.module.cjs.map +1 -1
  529. package/dist/components/Form/Form.module.js.map +1 -1
  530. package/dist/components/HoverCard/HoverCard.cjs.map +1 -1
  531. package/dist/components/HoverCard/HoverCard.js.map +1 -1
  532. package/dist/components/HoverCard/HoverCard.module.cjs.map +1 -1
  533. package/dist/components/HoverCard/HoverCard.module.js.map +1 -1
  534. package/dist/components/Image/Image.cjs.map +1 -1
  535. package/dist/components/Image/Image.js.map +1 -1
  536. package/dist/components/Image/Image.module.cjs.map +1 -1
  537. package/dist/components/Image/Image.module.js.map +1 -1
  538. package/dist/components/ImageCropper/ImageCropper.cjs +1 -1
  539. package/dist/components/ImageCropper/ImageCropper.cjs.map +1 -1
  540. package/dist/components/ImageCropper/ImageCropper.js +4 -8
  541. package/dist/components/ImageCropper/ImageCropper.js.map +1 -1
  542. package/dist/components/ImageCropper/ImageCropper.module.cjs.map +1 -1
  543. package/dist/components/ImageCropper/ImageCropper.module.js.map +1 -1
  544. package/dist/components/ImageCropper/crop-geometry.cjs.map +1 -1
  545. package/dist/components/ImageCropper/crop-geometry.js.map +1 -1
  546. package/dist/components/Input/Input.cjs.map +1 -1
  547. package/dist/components/Input/Input.js.map +1 -1
  548. package/dist/components/Input/Input.module.cjs.map +1 -1
  549. package/dist/components/Input/Input.module.js.map +1 -1
  550. package/dist/components/InstallBanner/InstallBanner.cjs.map +1 -1
  551. package/dist/components/InstallBanner/InstallBanner.js.map +1 -1
  552. package/dist/components/InstallBanner/InstallBanner.module.cjs.map +1 -1
  553. package/dist/components/InstallBanner/InstallBanner.module.js.map +1 -1
  554. package/dist/components/InstallButton/InstallButton.cjs.map +1 -1
  555. package/dist/components/InstallButton/InstallButton.js.map +1 -1
  556. package/dist/components/InstallButton/InstallButton.module.cjs.map +1 -1
  557. package/dist/components/InstallButton/InstallButton.module.js.map +1 -1
  558. package/dist/components/InstallButton/install-hints.cjs.map +1 -1
  559. package/dist/components/InstallButton/install-hints.js.map +1 -1
  560. package/dist/components/Kanban/Kanban.cjs.map +1 -1
  561. package/dist/components/Kanban/Kanban.js.map +1 -1
  562. package/dist/components/Kanban/Kanban.module.cjs.map +1 -1
  563. package/dist/components/Kanban/Kanban.module.js.map +1 -1
  564. package/dist/components/Kbd/Kbd.cjs.map +1 -1
  565. package/dist/components/Kbd/Kbd.js.map +1 -1
  566. package/dist/components/Kbd/Kbd.module.cjs.map +1 -1
  567. package/dist/components/Kbd/Kbd.module.js.map +1 -1
  568. package/dist/components/Label/Label.cjs.map +1 -1
  569. package/dist/components/Label/Label.js.map +1 -1
  570. package/dist/components/Label/Label.module.cjs.map +1 -1
  571. package/dist/components/Label/Label.module.js.map +1 -1
  572. package/dist/components/Layout/Layout.cjs.map +1 -1
  573. package/dist/components/Layout/Layout.js.map +1 -1
  574. package/dist/components/Layout/Layout.module.cjs.map +1 -1
  575. package/dist/components/Layout/Layout.module.js.map +1 -1
  576. package/dist/components/Lightbox/Lightbox.cjs +1 -1
  577. package/dist/components/Lightbox/Lightbox.cjs.map +1 -1
  578. package/dist/components/Lightbox/Lightbox.js +1 -1
  579. package/dist/components/Lightbox/Lightbox.js.map +1 -1
  580. package/dist/components/Lightbox/Lightbox.module.cjs.map +1 -1
  581. package/dist/components/Lightbox/Lightbox.module.js.map +1 -1
  582. package/dist/components/ListTile/ListTile.cjs.map +1 -1
  583. package/dist/components/ListTile/ListTile.js.map +1 -1
  584. package/dist/components/ListTile/ListTile.module.cjs.map +1 -1
  585. package/dist/components/ListTile/ListTile.module.js.map +1 -1
  586. package/dist/components/Markdown/Markdown.cjs.map +1 -1
  587. package/dist/components/Markdown/Markdown.js.map +1 -1
  588. package/dist/components/Markdown/Markdown.module.cjs.map +1 -1
  589. package/dist/components/Markdown/Markdown.module.js.map +1 -1
  590. package/dist/components/Markdown/markdown-parse.cjs +6 -6
  591. package/dist/components/Markdown/markdown-parse.cjs.map +1 -1
  592. package/dist/components/Markdown/markdown-parse.js +94 -96
  593. package/dist/components/Markdown/markdown-parse.js.map +1 -1
  594. package/dist/components/Masonry/Masonry.cjs.map +1 -1
  595. package/dist/components/Masonry/Masonry.js.map +1 -1
  596. package/dist/components/Masonry/Masonry.module.cjs.map +1 -1
  597. package/dist/components/Masonry/Masonry.module.js.map +1 -1
  598. package/dist/components/Masonry/masonry-layout.cjs.map +1 -1
  599. package/dist/components/Masonry/masonry-layout.js.map +1 -1
  600. package/dist/components/Menubar/Menubar.cjs.map +1 -1
  601. package/dist/components/Menubar/Menubar.js.map +1 -1
  602. package/dist/components/Menubar/Menubar.module.cjs.map +1 -1
  603. package/dist/components/Menubar/Menubar.module.js.map +1 -1
  604. package/dist/components/Modal/Modal.cjs.map +1 -1
  605. package/dist/components/Modal/Modal.js.map +1 -1
  606. package/dist/components/Modal/Modal.module.cjs.map +1 -1
  607. package/dist/components/Modal/Modal.module.js.map +1 -1
  608. package/dist/components/ModalsManager/ModalsManager.cjs.map +1 -1
  609. package/dist/components/ModalsManager/ModalsManager.js.map +1 -1
  610. package/dist/components/ModalsManager/ModalsManager.module.cjs.map +1 -1
  611. package/dist/components/ModalsManager/ModalsManager.module.js.map +1 -1
  612. package/dist/components/Money/Money.cjs.map +1 -1
  613. package/dist/components/Money/Money.js.map +1 -1
  614. package/dist/components/MultiSelect/MultiSelect.cjs.map +1 -1
  615. package/dist/components/MultiSelect/MultiSelect.js.map +1 -1
  616. package/dist/components/MultiSelect/MultiSelect.module.cjs.map +1 -1
  617. package/dist/components/MultiSelect/MultiSelect.module.js.map +1 -1
  618. package/dist/components/NProgress/NProgress.cjs.map +1 -1
  619. package/dist/components/NProgress/NProgress.js.map +1 -1
  620. package/dist/components/NProgress/NProgress.module.cjs.map +1 -1
  621. package/dist/components/NProgress/NProgress.module.js.map +1 -1
  622. package/dist/components/Navbar/Navbar.cjs.map +1 -1
  623. package/dist/components/Navbar/Navbar.js.map +1 -1
  624. package/dist/components/Navbar/Navbar.module.cjs.map +1 -1
  625. package/dist/components/Navbar/Navbar.module.js.map +1 -1
  626. package/dist/components/NavigationMenu/NavigationMenu.cjs.map +1 -1
  627. package/dist/components/NavigationMenu/NavigationMenu.js.map +1 -1
  628. package/dist/components/NavigationMenu/NavigationMenu.module.cjs.map +1 -1
  629. package/dist/components/NavigationMenu/NavigationMenu.module.js.map +1 -1
  630. package/dist/components/NavigationRail/NavigationRail.cjs.map +1 -1
  631. package/dist/components/NavigationRail/NavigationRail.js.map +1 -1
  632. package/dist/components/NavigationRail/NavigationRail.module.cjs.map +1 -1
  633. package/dist/components/NavigationRail/NavigationRail.module.js.map +1 -1
  634. package/dist/components/NotificationCenter/NotificationCenter.cjs.map +1 -1
  635. package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
  636. package/dist/components/NotificationCenter/NotificationCenter.module.cjs.map +1 -1
  637. package/dist/components/NotificationCenter/NotificationCenter.module.js.map +1 -1
  638. package/dist/components/NotificationCenter/use-notification-inbox.cjs.map +1 -1
  639. package/dist/components/NotificationCenter/use-notification-inbox.js.map +1 -1
  640. package/dist/components/OfflineIndicator/OfflineIndicator.cjs.map +1 -1
  641. package/dist/components/OfflineIndicator/OfflineIndicator.js.map +1 -1
  642. package/dist/components/OfflineIndicator/OfflineIndicator.module.cjs.map +1 -1
  643. package/dist/components/OfflineIndicator/OfflineIndicator.module.js.map +1 -1
  644. package/dist/components/Page/Page.cjs.map +1 -1
  645. package/dist/components/Page/Page.js.map +1 -1
  646. package/dist/components/Page/Page.module.cjs.map +1 -1
  647. package/dist/components/Page/Page.module.js.map +1 -1
  648. package/dist/components/Pagination/Pagination.cjs.map +1 -1
  649. package/dist/components/Pagination/Pagination.js.map +1 -1
  650. package/dist/components/Pagination/Pagination.module.cjs.map +1 -1
  651. package/dist/components/Pagination/Pagination.module.js.map +1 -1
  652. package/dist/components/PasswordInput/PasswordInput.cjs.map +1 -1
  653. package/dist/components/PasswordInput/PasswordInput.js.map +1 -1
  654. package/dist/components/PasswordInput/PasswordInput.module.cjs.map +1 -1
  655. package/dist/components/PasswordInput/PasswordInput.module.js.map +1 -1
  656. package/dist/components/PinInput/PinInput.cjs.map +1 -1
  657. package/dist/components/PinInput/PinInput.js.map +1 -1
  658. package/dist/components/PinInput/PinInput.module.cjs.map +1 -1
  659. package/dist/components/PinInput/PinInput.module.js.map +1 -1
  660. package/dist/components/Popover/Popover.cjs.map +1 -1
  661. package/dist/components/Popover/Popover.js.map +1 -1
  662. package/dist/components/Popover/Popover.module.cjs.map +1 -1
  663. package/dist/components/Popover/Popover.module.js.map +1 -1
  664. package/dist/components/Portal/Portal.cjs.map +1 -1
  665. package/dist/components/Portal/Portal.js.map +1 -1
  666. package/dist/components/Portal/anchor-position.cjs.map +1 -1
  667. package/dist/components/Portal/anchor-position.js.map +1 -1
  668. package/dist/components/Portal/escape-layer.cjs.map +1 -1
  669. package/dist/components/Portal/escape-layer.js.map +1 -1
  670. package/dist/components/Portal/portal-host.cjs.map +1 -1
  671. package/dist/components/Portal/portal-host.js.map +1 -1
  672. package/dist/components/Portal/tab-bridge.cjs +1 -1
  673. package/dist/components/Portal/tab-bridge.cjs.map +1 -1
  674. package/dist/components/Portal/tab-bridge.js +1 -5
  675. package/dist/components/Portal/tab-bridge.js.map +1 -1
  676. package/dist/components/Progress/Progress.cjs.map +1 -1
  677. package/dist/components/Progress/Progress.js.map +1 -1
  678. package/dist/components/Progress/Progress.module.cjs.map +1 -1
  679. package/dist/components/Progress/Progress.module.js.map +1 -1
  680. package/dist/components/QRCode/QRCode.cjs.map +1 -1
  681. package/dist/components/QRCode/QRCode.js.map +1 -1
  682. package/dist/components/QRCode/QRCode.module.cjs.map +1 -1
  683. package/dist/components/QRCode/QRCode.module.js.map +1 -1
  684. package/dist/components/QRCode/qr-encode.cjs +1 -1
  685. package/dist/components/QRCode/qr-encode.cjs.map +1 -1
  686. package/dist/components/QRCode/qr-encode.js +7 -13
  687. package/dist/components/QRCode/qr-encode.js.map +1 -1
  688. package/dist/components/QRCode/qr-tables.cjs.map +1 -1
  689. package/dist/components/QRCode/qr-tables.js.map +1 -1
  690. package/dist/components/Radio/Radio.cjs.map +1 -1
  691. package/dist/components/Radio/Radio.js.map +1 -1
  692. package/dist/components/Radio/Radio.module.cjs.map +1 -1
  693. package/dist/components/Radio/Radio.module.js.map +1 -1
  694. package/dist/components/RangeSlider/RangeSlider.cjs.map +1 -1
  695. package/dist/components/RangeSlider/RangeSlider.js.map +1 -1
  696. package/dist/components/RangeSlider/RangeSlider.module.cjs.map +1 -1
  697. package/dist/components/RangeSlider/RangeSlider.module.js.map +1 -1
  698. package/dist/components/RatingStars/RatingStars.cjs.map +1 -1
  699. package/dist/components/RatingStars/RatingStars.js.map +1 -1
  700. package/dist/components/RatingStars/RatingStars.module.cjs.map +1 -1
  701. package/dist/components/RatingStars/RatingStars.module.js.map +1 -1
  702. package/dist/components/RefreshIndicator/RefreshIndicator.cjs +1 -1
  703. package/dist/components/RefreshIndicator/RefreshIndicator.cjs.map +1 -1
  704. package/dist/components/RefreshIndicator/RefreshIndicator.js +10 -18
  705. package/dist/components/RefreshIndicator/RefreshIndicator.js.map +1 -1
  706. package/dist/components/RefreshIndicator/RefreshIndicator.module.cjs.map +1 -1
  707. package/dist/components/RefreshIndicator/RefreshIndicator.module.js.map +1 -1
  708. package/dist/components/RelativeTime/RelativeTime.cjs.map +1 -1
  709. package/dist/components/RelativeTime/RelativeTime.js.map +1 -1
  710. package/dist/components/Resizable/Resizable.cjs +1 -1
  711. package/dist/components/Resizable/Resizable.cjs.map +1 -1
  712. package/dist/components/Resizable/Resizable.js +1 -9
  713. package/dist/components/Resizable/Resizable.js.map +1 -1
  714. package/dist/components/Resizable/Resizable.module.cjs.map +1 -1
  715. package/dist/components/Resizable/Resizable.module.js.map +1 -1
  716. package/dist/components/Responsive/Responsive.cjs.map +1 -1
  717. package/dist/components/Responsive/Responsive.js.map +1 -1
  718. package/dist/components/Reveal/Reveal.cjs.map +1 -1
  719. package/dist/components/Reveal/Reveal.js.map +1 -1
  720. package/dist/components/Reveal/Reveal.module.cjs.map +1 -1
  721. package/dist/components/Reveal/Reveal.module.js.map +1 -1
  722. package/dist/components/Reveal/reveal-threshold.cjs.map +1 -1
  723. package/dist/components/Reveal/reveal-threshold.js.map +1 -1
  724. package/dist/components/SafeArea/SafeArea.cjs.map +1 -1
  725. package/dist/components/SafeArea/SafeArea.js.map +1 -1
  726. package/dist/components/SafeArea/SafeArea.module.cjs.map +1 -1
  727. package/dist/components/SafeArea/SafeArea.module.js.map +1 -1
  728. package/dist/components/Scheduler/Scheduler.cjs.map +1 -1
  729. package/dist/components/Scheduler/Scheduler.js.map +1 -1
  730. package/dist/components/Scheduler/Scheduler.module.cjs.map +1 -1
  731. package/dist/components/Scheduler/Scheduler.module.js.map +1 -1
  732. package/dist/components/Scheduler/scheduler-layout.cjs.map +1 -1
  733. package/dist/components/Scheduler/scheduler-layout.js.map +1 -1
  734. package/dist/components/ScrollArea/ScrollArea.cjs.map +1 -1
  735. package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
  736. package/dist/components/ScrollArea/ScrollArea.module.cjs.map +1 -1
  737. package/dist/components/ScrollArea/ScrollArea.module.js.map +1 -1
  738. package/dist/components/SearchBar/SearchBar.cjs.map +1 -1
  739. package/dist/components/SearchBar/SearchBar.js.map +1 -1
  740. package/dist/components/SearchBar/SearchBar.module.cjs.map +1 -1
  741. package/dist/components/SearchBar/SearchBar.module.js.map +1 -1
  742. package/dist/components/SectionHeader/SectionHeader.cjs.map +1 -1
  743. package/dist/components/SectionHeader/SectionHeader.js.map +1 -1
  744. package/dist/components/SectionHeader/SectionHeader.module.cjs.map +1 -1
  745. package/dist/components/SectionHeader/SectionHeader.module.js.map +1 -1
  746. package/dist/components/SegmentedControl/SegmentedControl.cjs.map +1 -1
  747. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  748. package/dist/components/SegmentedControl/SegmentedControl.module.cjs.map +1 -1
  749. package/dist/components/SegmentedControl/SegmentedControl.module.js.map +1 -1
  750. package/dist/components/Select/CaretIcon.cjs.map +1 -1
  751. package/dist/components/Select/CaretIcon.js.map +1 -1
  752. package/dist/components/Select/Select.cjs.map +1 -1
  753. package/dist/components/Select/Select.js.map +1 -1
  754. package/dist/components/Select/Select.module.cjs.map +1 -1
  755. package/dist/components/Select/Select.module.js.map +1 -1
  756. package/dist/components/Select/options.cjs.map +1 -1
  757. package/dist/components/Select/options.js.map +1 -1
  758. package/dist/components/Sidebar/Sidebar.cjs +1 -1
  759. package/dist/components/Sidebar/Sidebar.cjs.map +1 -1
  760. package/dist/components/Sidebar/Sidebar.js +13 -23
  761. package/dist/components/Sidebar/Sidebar.js.map +1 -1
  762. package/dist/components/Sidebar/Sidebar.module.cjs.map +1 -1
  763. package/dist/components/Sidebar/Sidebar.module.js.map +1 -1
  764. package/dist/components/Sidebar/SidebarEntry.cjs.map +1 -1
  765. package/dist/components/Sidebar/SidebarEntry.js.map +1 -1
  766. package/dist/components/Sidebar/active-nav-key.cjs.map +1 -1
  767. package/dist/components/Sidebar/active-nav-key.js.map +1 -1
  768. package/dist/components/SignaturePad/SignaturePad.cjs +1 -1
  769. package/dist/components/SignaturePad/SignaturePad.cjs.map +1 -1
  770. package/dist/components/SignaturePad/SignaturePad.js +1 -5
  771. package/dist/components/SignaturePad/SignaturePad.js.map +1 -1
  772. package/dist/components/SignaturePad/SignaturePad.module.cjs.map +1 -1
  773. package/dist/components/SignaturePad/SignaturePad.module.js.map +1 -1
  774. package/dist/components/Skeleton/Skeleton.cjs.map +1 -1
  775. package/dist/components/Skeleton/Skeleton.js.map +1 -1
  776. package/dist/components/Skeleton/Skeleton.module.cjs.map +1 -1
  777. package/dist/components/Skeleton/Skeleton.module.js.map +1 -1
  778. package/dist/components/Slider/Slider.cjs.map +1 -1
  779. package/dist/components/Slider/Slider.js.map +1 -1
  780. package/dist/components/Slider/Slider.module.cjs.map +1 -1
  781. package/dist/components/Slider/Slider.module.js.map +1 -1
  782. package/dist/components/Spacer/Spacer.cjs.map +1 -1
  783. package/dist/components/Spacer/Spacer.js.map +1 -1
  784. package/dist/components/Spacer/Spacer.module.cjs.map +1 -1
  785. package/dist/components/Spacer/Spacer.module.js.map +1 -1
  786. package/dist/components/Sparkline/Sparkline.cjs.map +1 -1
  787. package/dist/components/Sparkline/Sparkline.js.map +1 -1
  788. package/dist/components/Sparkline/Sparkline.module.cjs.map +1 -1
  789. package/dist/components/Sparkline/Sparkline.module.js.map +1 -1
  790. package/dist/components/Sparkline/sparkline-geometry.cjs.map +1 -1
  791. package/dist/components/Sparkline/sparkline-geometry.js.map +1 -1
  792. package/dist/components/Spinner/Spinner.cjs.map +1 -1
  793. package/dist/components/Spinner/Spinner.js.map +1 -1
  794. package/dist/components/Spinner/Spinner.module.cjs.map +1 -1
  795. package/dist/components/Spinner/Spinner.module.js.map +1 -1
  796. package/dist/components/Stat/Stat.cjs.map +1 -1
  797. package/dist/components/Stat/Stat.js.map +1 -1
  798. package/dist/components/Stat/Stat.module.cjs.map +1 -1
  799. package/dist/components/Stat/Stat.module.js.map +1 -1
  800. package/dist/components/Stepper/Stepper.cjs.map +1 -1
  801. package/dist/components/Stepper/Stepper.js.map +1 -1
  802. package/dist/components/Stepper/Stepper.module.cjs.map +1 -1
  803. package/dist/components/Stepper/Stepper.module.js.map +1 -1
  804. package/dist/components/StepperInput/StepperInput.cjs.map +1 -1
  805. package/dist/components/StepperInput/StepperInput.js.map +1 -1
  806. package/dist/components/StepperInput/StepperInput.module.cjs.map +1 -1
  807. package/dist/components/StepperInput/StepperInput.module.js.map +1 -1
  808. package/dist/components/Switch/Switch.cjs.map +1 -1
  809. package/dist/components/Switch/Switch.js.map +1 -1
  810. package/dist/components/Switch/Switch.module.cjs.map +1 -1
  811. package/dist/components/Switch/Switch.module.js.map +1 -1
  812. package/dist/components/SyncStatusBadge/SyncStatusBadge.cjs.map +1 -1
  813. package/dist/components/SyncStatusBadge/SyncStatusBadge.js.map +1 -1
  814. package/dist/components/SyncStatusBadge/SyncStatusBadge.module.cjs.map +1 -1
  815. package/dist/components/SyncStatusBadge/SyncStatusBadge.module.js.map +1 -1
  816. package/dist/components/Table/Table.cjs.map +1 -1
  817. package/dist/components/Table/Table.js.map +1 -1
  818. package/dist/components/Table/Table.module.cjs.map +1 -1
  819. package/dist/components/Table/Table.module.js.map +1 -1
  820. package/dist/components/Tabs/Tabs.cjs.map +1 -1
  821. package/dist/components/Tabs/Tabs.js.map +1 -1
  822. package/dist/components/Tabs/Tabs.module.cjs.map +1 -1
  823. package/dist/components/Tabs/Tabs.module.js.map +1 -1
  824. package/dist/components/Tag/Tag.cjs.map +1 -1
  825. package/dist/components/Tag/Tag.js.map +1 -1
  826. package/dist/components/Tag/Tag.module.cjs.map +1 -1
  827. package/dist/components/Tag/Tag.module.js.map +1 -1
  828. package/dist/components/Textarea/Textarea.cjs.map +1 -1
  829. package/dist/components/Textarea/Textarea.js.map +1 -1
  830. package/dist/components/Textarea/Textarea.module.cjs.map +1 -1
  831. package/dist/components/Textarea/Textarea.module.js.map +1 -1
  832. package/dist/components/TimePicker/TimePicker.cjs.map +1 -1
  833. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  834. package/dist/components/TimePicker/TimePicker.module.cjs.map +1 -1
  835. package/dist/components/TimePicker/TimePicker.module.js.map +1 -1
  836. package/dist/components/Timeline/Timeline.cjs.map +1 -1
  837. package/dist/components/Timeline/Timeline.js.map +1 -1
  838. package/dist/components/Timeline/Timeline.module.cjs.map +1 -1
  839. package/dist/components/Timeline/Timeline.module.js.map +1 -1
  840. package/dist/components/Toast/Toast.module.cjs.map +1 -1
  841. package/dist/components/Toast/Toast.module.js.map +1 -1
  842. package/dist/components/Toast/ToastProvider.cjs.map +1 -1
  843. package/dist/components/Toast/ToastProvider.js.map +1 -1
  844. package/dist/components/Toggle/Toggle.cjs.map +1 -1
  845. package/dist/components/Toggle/Toggle.js.map +1 -1
  846. package/dist/components/Toggle/Toggle.module.cjs.map +1 -1
  847. package/dist/components/Toggle/Toggle.module.js.map +1 -1
  848. package/dist/components/ToggleGroup/ToggleGroup.cjs.map +1 -1
  849. package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
  850. package/dist/components/ToggleGroup/ToggleGroup.module.cjs.map +1 -1
  851. package/dist/components/ToggleGroup/ToggleGroup.module.js.map +1 -1
  852. package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
  853. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  854. package/dist/components/Tooltip/Tooltip.module.cjs.map +1 -1
  855. package/dist/components/Tooltip/Tooltip.module.js.map +1 -1
  856. package/dist/components/Tour/Tour.cjs +1 -1
  857. package/dist/components/Tour/Tour.cjs.map +1 -1
  858. package/dist/components/Tour/Tour.js +1 -5
  859. package/dist/components/Tour/Tour.js.map +1 -1
  860. package/dist/components/Tour/Tour.module.cjs.map +1 -1
  861. package/dist/components/Tour/Tour.module.js.map +1 -1
  862. package/dist/components/Tour/tour-position.cjs.map +1 -1
  863. package/dist/components/Tour/tour-position.js.map +1 -1
  864. package/dist/components/Transfer/Transfer.cjs.map +1 -1
  865. package/dist/components/Transfer/Transfer.js.map +1 -1
  866. package/dist/components/Transfer/Transfer.module.cjs.map +1 -1
  867. package/dist/components/Transfer/Transfer.module.js.map +1 -1
  868. package/dist/components/Transfer/transfer-state.cjs.map +1 -1
  869. package/dist/components/Transfer/transfer-state.js.map +1 -1
  870. package/dist/components/TreeView/TreeView.cjs.map +1 -1
  871. package/dist/components/TreeView/TreeView.js.map +1 -1
  872. package/dist/components/TreeView/TreeView.module.cjs.map +1 -1
  873. package/dist/components/TreeView/TreeView.module.js.map +1 -1
  874. package/dist/components/TruncateText/TruncateText.cjs.map +1 -1
  875. package/dist/components/TruncateText/TruncateText.js.map +1 -1
  876. package/dist/components/TruncateText/TruncateText.module.cjs.map +1 -1
  877. package/dist/components/TruncateText/TruncateText.module.js.map +1 -1
  878. package/dist/components/UpdatePrompt/UpdatePrompt.cjs.map +1 -1
  879. package/dist/components/UpdatePrompt/UpdatePrompt.js.map +1 -1
  880. package/dist/components/UpdatePrompt/UpdatePrompt.module.cjs.map +1 -1
  881. package/dist/components/UpdatePrompt/UpdatePrompt.module.js.map +1 -1
  882. package/dist/components/VideoPlayer/VideoPlayer.cjs +1 -1
  883. package/dist/components/VideoPlayer/VideoPlayer.cjs.map +1 -1
  884. package/dist/components/VideoPlayer/VideoPlayer.js +1 -7
  885. package/dist/components/VideoPlayer/VideoPlayer.js.map +1 -1
  886. package/dist/components/VideoPlayer/VideoPlayer.module.cjs.map +1 -1
  887. package/dist/components/VideoPlayer/VideoPlayer.module.js.map +1 -1
  888. package/dist/components/VideoPlayer/playback-rates.cjs.map +1 -1
  889. package/dist/components/VideoPlayer/playback-rates.js.map +1 -1
  890. package/dist/components/VirtualList/VirtualList.cjs.map +1 -1
  891. package/dist/components/VirtualList/VirtualList.js.map +1 -1
  892. package/dist/components/VirtualList/VirtualList.module.cjs.map +1 -1
  893. package/dist/components/VirtualList/VirtualList.module.js.map +1 -1
  894. package/dist/components/VirtualTable/VirtualTable.cjs.map +1 -1
  895. package/dist/components/VirtualTable/VirtualTable.js.map +1 -1
  896. package/dist/components/VirtualTable/VirtualTable.module.cjs.map +1 -1
  897. package/dist/components/VirtualTable/VirtualTable.module.js.map +1 -1
  898. package/dist/components/VisuallyHidden/VisuallyHidden.cjs.map +1 -1
  899. package/dist/components/VisuallyHidden/VisuallyHidden.js.map +1 -1
  900. package/dist/components/VisuallyHidden/VisuallyHidden.module.cjs.map +1 -1
  901. package/dist/components/VisuallyHidden/VisuallyHidden.module.js.map +1 -1
  902. package/dist/components/Wizard/Wizard.cjs +1 -1
  903. package/dist/components/Wizard/Wizard.cjs.map +1 -1
  904. package/dist/components/Wizard/Wizard.js +4 -11
  905. package/dist/components/Wizard/Wizard.js.map +1 -1
  906. package/dist/components/Wizard/Wizard.module.cjs.map +1 -1
  907. package/dist/components/Wizard/Wizard.module.js.map +1 -1
  908. package/dist/data/create-data-provider.cjs.map +1 -1
  909. package/dist/data/create-data-provider.js.map +1 -1
  910. package/dist/data/data-provider-context.cjs.map +1 -1
  911. package/dist/data/data-provider-context.js.map +1 -1
  912. package/dist/data/use-resource.cjs.map +1 -1
  913. package/dist/data/use-resource.js.map +1 -1
  914. package/dist/editor/RichTextEditor.cjs.map +1 -1
  915. package/dist/editor/RichTextEditor.js.map +1 -1
  916. package/dist/editor/RichTextEditor.module.cjs.map +1 -1
  917. package/dist/editor/RichTextEditor.module.js.map +1 -1
  918. package/dist/editor.js +1 -2
  919. package/dist/error-boundary/ErrorBoundary.cjs.map +1 -1
  920. package/dist/error-boundary/ErrorBoundary.js.map +1 -1
  921. package/dist/error-boundary/use-error-handler.cjs.map +1 -1
  922. package/dist/error-boundary/use-error-handler.js.map +1 -1
  923. package/dist/feature-flags/FeatureFlagsProvider.cjs.map +1 -1
  924. package/dist/feature-flags/FeatureFlagsProvider.js.map +1 -1
  925. package/dist/feature-flags/growthbook-adapter.cjs.map +1 -1
  926. package/dist/feature-flags/growthbook-adapter.js.map +1 -1
  927. package/dist/feature-flags/in-memory-adapter.cjs.map +1 -1
  928. package/dist/feature-flags/in-memory-adapter.js.map +1 -1
  929. package/dist/feature-flags/launchdarkly-adapter.cjs.map +1 -1
  930. package/dist/feature-flags/launchdarkly-adapter.js.map +1 -1
  931. package/dist/forms/FormField.cjs.map +1 -1
  932. package/dist/forms/FormField.js.map +1 -1
  933. package/dist/forms/br-validators.cjs.map +1 -1
  934. package/dist/forms/br-validators.js.map +1 -1
  935. package/dist/forms/masked-inputs.cjs.map +1 -1
  936. package/dist/forms/masked-inputs.js.map +1 -1
  937. package/dist/forms/use-viacep.cjs.map +1 -1
  938. package/dist/forms/use-viacep.js.map +1 -1
  939. package/dist/forms/use-zod-form.cjs.map +1 -1
  940. package/dist/forms/use-zod-form.js.map +1 -1
  941. package/dist/forms/validate-form.cjs.map +1 -1
  942. package/dist/forms/validate-form.js.map +1 -1
  943. package/dist/forms/zod-resolver.cjs.map +1 -1
  944. package/dist/forms/zod-resolver.js.map +1 -1
  945. package/dist/geo/TrajectoryMap.cjs.map +1 -1
  946. package/dist/geo/TrajectoryMap.js.map +1 -1
  947. package/dist/geo/TrajectoryMap.module.cjs.map +1 -1
  948. package/dist/geo/TrajectoryMap.module.js.map +1 -1
  949. package/dist/geo/bounds.cjs.map +1 -1
  950. package/dist/geo/bounds.js.map +1 -1
  951. package/dist/geo/create-position-tracker.cjs +1 -1
  952. package/dist/geo/create-position-tracker.cjs.map +1 -1
  953. package/dist/geo/create-position-tracker.js +1 -7
  954. package/dist/geo/create-position-tracker.js.map +1 -1
  955. package/dist/geo/distance.cjs.map +1 -1
  956. package/dist/geo/distance.js.map +1 -1
  957. package/dist/geo/estimate.cjs.map +1 -1
  958. package/dist/geo/estimate.js.map +1 -1
  959. package/dist/geo/leaflet-map.cjs.map +1 -1
  960. package/dist/geo/leaflet-map.js.map +1 -1
  961. package/dist/geo/projection.cjs.map +1 -1
  962. package/dist/geo/projection.js.map +1 -1
  963. package/dist/geo/routing.cjs.map +1 -1
  964. package/dist/geo/routing.js.map +1 -1
  965. package/dist/geo/types.cjs.map +1 -1
  966. package/dist/geo/types.js.map +1 -1
  967. package/dist/geo/use-position-tracker.cjs.map +1 -1
  968. package/dist/geo/use-position-tracker.js.map +1 -1
  969. package/dist/hooks/pwa-env.cjs.map +1 -1
  970. package/dist/hooks/pwa-env.js.map +1 -1
  971. package/dist/hooks/tab-sequence.cjs.map +1 -1
  972. package/dist/hooks/tab-sequence.js.map +1 -1
  973. package/dist/hooks/use-announce.cjs +1 -1
  974. package/dist/hooks/use-announce.cjs.map +1 -1
  975. package/dist/hooks/use-announce.js +2 -2
  976. package/dist/hooks/use-announce.js.map +1 -1
  977. package/dist/hooks/use-async.cjs.map +1 -1
  978. package/dist/hooks/use-async.js.map +1 -1
  979. package/dist/hooks/use-before-install-prompt.cjs.map +1 -1
  980. package/dist/hooks/use-before-install-prompt.js.map +1 -1
  981. package/dist/hooks/use-breakpoint.cjs.map +1 -1
  982. package/dist/hooks/use-breakpoint.js.map +1 -1
  983. package/dist/hooks/use-click-outside.cjs.map +1 -1
  984. package/dist/hooks/use-click-outside.js.map +1 -1
  985. package/dist/hooks/use-client-filter.cjs.map +1 -1
  986. package/dist/hooks/use-client-filter.js.map +1 -1
  987. package/dist/hooks/use-clipboard.cjs.map +1 -1
  988. package/dist/hooks/use-clipboard.js.map +1 -1
  989. package/dist/hooks/use-countdown.cjs.map +1 -1
  990. package/dist/hooks/use-countdown.js.map +1 -1
  991. package/dist/hooks/use-counter.cjs.map +1 -1
  992. package/dist/hooks/use-counter.js.map +1 -1
  993. package/dist/hooks/use-debounce.cjs.map +1 -1
  994. package/dist/hooks/use-debounce.js.map +1 -1
  995. package/dist/hooks/use-deep-memo.cjs.map +1 -1
  996. package/dist/hooks/use-deep-memo.js.map +1 -1
  997. package/dist/hooks/use-disclosure.cjs.map +1 -1
  998. package/dist/hooks/use-disclosure.js.map +1 -1
  999. package/dist/hooks/use-document-title.cjs.map +1 -1
  1000. package/dist/hooks/use-document-title.js.map +1 -1
  1001. package/dist/hooks/use-document-visibility.cjs.map +1 -1
  1002. package/dist/hooks/use-document-visibility.js.map +1 -1
  1003. package/dist/hooks/use-draft-filters.cjs.map +1 -1
  1004. package/dist/hooks/use-draft-filters.js.map +1 -1
  1005. package/dist/hooks/use-event-listener.cjs.map +1 -1
  1006. package/dist/hooks/use-event-listener.js.map +1 -1
  1007. package/dist/hooks/use-favicon.cjs.map +1 -1
  1008. package/dist/hooks/use-favicon.js.map +1 -1
  1009. package/dist/hooks/use-focus-trap.cjs.map +1 -1
  1010. package/dist/hooks/use-focus-trap.js.map +1 -1
  1011. package/dist/hooks/use-fullscreen-element.cjs.map +1 -1
  1012. package/dist/hooks/use-fullscreen-element.js.map +1 -1
  1013. package/dist/hooks/use-fullscreen.cjs +1 -1
  1014. package/dist/hooks/use-fullscreen.cjs.map +1 -1
  1015. package/dist/hooks/use-fullscreen.js +7 -23
  1016. package/dist/hooks/use-fullscreen.js.map +1 -1
  1017. package/dist/hooks/use-geolocation.cjs.map +1 -1
  1018. package/dist/hooks/use-geolocation.js.map +1 -1
  1019. package/dist/hooks/use-hover.cjs.map +1 -1
  1020. package/dist/hooks/use-hover.js.map +1 -1
  1021. package/dist/hooks/use-idle.cjs.map +1 -1
  1022. package/dist/hooks/use-idle.js.map +1 -1
  1023. package/dist/hooks/use-install-prompt.cjs +1 -1
  1024. package/dist/hooks/use-install-prompt.cjs.map +1 -1
  1025. package/dist/hooks/use-install-prompt.js +1 -1
  1026. package/dist/hooks/use-install-prompt.js.map +1 -1
  1027. package/dist/hooks/use-intersection-observer.cjs.map +1 -1
  1028. package/dist/hooks/use-intersection-observer.js.map +1 -1
  1029. package/dist/hooks/use-interval.cjs.map +1 -1
  1030. package/dist/hooks/use-interval.js.map +1 -1
  1031. package/dist/hooks/use-is-first-render.cjs.map +1 -1
  1032. package/dist/hooks/use-is-first-render.js.map +1 -1
  1033. package/dist/hooks/use-keyboard-shortcut.cjs.map +1 -1
  1034. package/dist/hooks/use-keyboard-shortcut.js.map +1 -1
  1035. package/dist/hooks/use-latest-ref.cjs.map +1 -1
  1036. package/dist/hooks/use-latest-ref.js.map +1 -1
  1037. package/dist/hooks/use-list-state.cjs.map +1 -1
  1038. package/dist/hooks/use-list-state.js.map +1 -1
  1039. package/dist/hooks/use-local-storage.cjs +1 -1
  1040. package/dist/hooks/use-local-storage.cjs.map +1 -1
  1041. package/dist/hooks/use-local-storage.js +2 -5
  1042. package/dist/hooks/use-local-storage.js.map +1 -1
  1043. package/dist/hooks/use-long-press-handlers.cjs.map +1 -1
  1044. package/dist/hooks/use-long-press-handlers.js.map +1 -1
  1045. package/dist/hooks/use-long-press.cjs.map +1 -1
  1046. package/dist/hooks/use-long-press.js.map +1 -1
  1047. package/dist/hooks/use-map.cjs.map +1 -1
  1048. package/dist/hooks/use-map.js.map +1 -1
  1049. package/dist/hooks/use-media-devices.cjs.map +1 -1
  1050. package/dist/hooks/use-media-devices.js.map +1 -1
  1051. package/dist/hooks/use-media-permission.cjs +1 -1
  1052. package/dist/hooks/use-media-permission.cjs.map +1 -1
  1053. package/dist/hooks/use-media-permission.js +2 -5
  1054. package/dist/hooks/use-media-permission.js.map +1 -1
  1055. package/dist/hooks/use-media-query.cjs.map +1 -1
  1056. package/dist/hooks/use-media-query.js.map +1 -1
  1057. package/dist/hooks/use-object-url.cjs.map +1 -1
  1058. package/dist/hooks/use-object-url.js.map +1 -1
  1059. package/dist/hooks/use-online.cjs.map +1 -1
  1060. package/dist/hooks/use-online.js.map +1 -1
  1061. package/dist/hooks/use-pagination.cjs.map +1 -1
  1062. package/dist/hooks/use-pagination.js.map +1 -1
  1063. package/dist/hooks/use-previous.cjs.map +1 -1
  1064. package/dist/hooks/use-previous.js.map +1 -1
  1065. package/dist/hooks/use-push-to-talk.cjs.map +1 -1
  1066. package/dist/hooks/use-push-to-talk.js.map +1 -1
  1067. package/dist/hooks/use-queue.cjs.map +1 -1
  1068. package/dist/hooks/use-queue.js.map +1 -1
  1069. package/dist/hooks/use-resize-observer.cjs.map +1 -1
  1070. package/dist/hooks/use-resize-observer.js.map +1 -1
  1071. package/dist/hooks/use-scroll-lock.cjs.map +1 -1
  1072. package/dist/hooks/use-scroll-lock.js.map +1 -1
  1073. package/dist/hooks/use-scroll-overflow.cjs.map +1 -1
  1074. package/dist/hooks/use-scroll-overflow.js.map +1 -1
  1075. package/dist/hooks/use-service-worker-update.cjs.map +1 -1
  1076. package/dist/hooks/use-service-worker-update.js.map +1 -1
  1077. package/dist/hooks/use-set.cjs.map +1 -1
  1078. package/dist/hooks/use-set.js.map +1 -1
  1079. package/dist/hooks/use-sortable.cjs.map +1 -1
  1080. package/dist/hooks/use-sortable.js.map +1 -1
  1081. package/dist/hooks/use-stable-callback.cjs.map +1 -1
  1082. package/dist/hooks/use-stable-callback.js.map +1 -1
  1083. package/dist/hooks/use-storage-estimate.cjs.map +1 -1
  1084. package/dist/hooks/use-storage-estimate.js.map +1 -1
  1085. package/dist/hooks/use-throttle.cjs.map +1 -1
  1086. package/dist/hooks/use-throttle.js.map +1 -1
  1087. package/dist/hooks/use-timeout.cjs.map +1 -1
  1088. package/dist/hooks/use-timeout.js.map +1 -1
  1089. package/dist/hooks/use-toggle.cjs.map +1 -1
  1090. package/dist/hooks/use-toggle.js.map +1 -1
  1091. package/dist/hooks/use-typewriter.cjs.map +1 -1
  1092. package/dist/hooks/use-typewriter.js.map +1 -1
  1093. package/dist/hooks/use-window-size.cjs.map +1 -1
  1094. package/dist/hooks/use-window-size.js.map +1 -1
  1095. package/dist/http/api-client.cjs.map +1 -1
  1096. package/dist/http/api-client.js.map +1 -1
  1097. package/dist/http/build-url.cjs.map +1 -1
  1098. package/dist/http/build-url.js.map +1 -1
  1099. package/dist/http/credential-scope.cjs.map +1 -1
  1100. package/dist/http/credential-scope.js.map +1 -1
  1101. package/dist/http/csrf.cjs.map +1 -1
  1102. package/dist/http/csrf.js.map +1 -1
  1103. package/dist/http/decode-response.cjs.map +1 -1
  1104. package/dist/http/decode-response.js.map +1 -1
  1105. package/dist/http/describe-api-error.cjs.map +1 -1
  1106. package/dist/http/describe-api-error.js.map +1 -1
  1107. package/dist/http/errors.cjs.map +1 -1
  1108. package/dist/http/errors.js.map +1 -1
  1109. package/dist/http/idempotency.cjs.map +1 -1
  1110. package/dist/http/idempotency.js.map +1 -1
  1111. package/dist/http/parse-response.cjs.map +1 -1
  1112. package/dist/http/parse-response.js.map +1 -1
  1113. package/dist/http/resumable-upload.cjs +1 -1
  1114. package/dist/http/resumable-upload.cjs.map +1 -1
  1115. package/dist/http/resumable-upload.js +141 -105
  1116. package/dist/http/resumable-upload.js.map +1 -1
  1117. package/dist/http/retry.cjs +1 -1
  1118. package/dist/http/retry.cjs.map +1 -1
  1119. package/dist/http/retry.js +5 -6
  1120. package/dist/http/retry.js.map +1 -1
  1121. package/dist/http/timeout.cjs.map +1 -1
  1122. package/dist/http/timeout.js.map +1 -1
  1123. package/dist/http/upload-with-progress.cjs +1 -1
  1124. package/dist/http/upload-with-progress.cjs.map +1 -1
  1125. package/dist/http/upload-with-progress.js +2 -7
  1126. package/dist/http/upload-with-progress.js.map +1 -1
  1127. package/dist/http/use-describe-api-error.cjs.map +1 -1
  1128. package/dist/http/use-describe-api-error.js.map +1 -1
  1129. package/dist/http/use-poll.cjs +1 -1
  1130. package/dist/http/use-poll.cjs.map +1 -1
  1131. package/dist/http/use-poll.js +2 -5
  1132. package/dist/http/use-poll.js.map +1 -1
  1133. package/dist/i18n/I18nProvider.cjs.map +1 -1
  1134. package/dist/i18n/I18nProvider.js.map +1 -1
  1135. package/dist/i18n/create-i18n.cjs.map +1 -1
  1136. package/dist/i18n/create-i18n.js.map +1 -1
  1137. package/dist/icons/Icon.cjs.map +1 -1
  1138. package/dist/icons/Icon.js.map +1 -1
  1139. package/dist/icons/IconPicker.cjs.map +1 -1
  1140. package/dist/icons/IconPicker.js.map +1 -1
  1141. package/dist/icons/IconPicker.module.cjs.map +1 -1
  1142. package/dist/icons/IconPicker.module.js.map +1 -1
  1143. package/dist/icons/IconProvider.cjs.map +1 -1
  1144. package/dist/icons/IconProvider.js.map +1 -1
  1145. package/dist/icons/alias.cjs.map +1 -1
  1146. package/dist/icons/alias.js.map +1 -1
  1147. package/dist/icons/generated/aliases.cjs.map +1 -1
  1148. package/dist/icons/generated/aliases.js.map +1 -1
  1149. package/dist/icons/generated/icon-names.cjs.map +1 -1
  1150. package/dist/icons/generated/icon-names.js.map +1 -1
  1151. package/dist/icons/generated/loaders.cjs.map +1 -1
  1152. package/dist/icons/generated/loaders.js.map +1 -1
  1153. package/dist/icons/generated/shard-00.cjs.map +1 -1
  1154. package/dist/icons/generated/shard-00.js.map +1 -1
  1155. package/dist/icons/generated/shard-01.cjs.map +1 -1
  1156. package/dist/icons/generated/shard-01.js.map +1 -1
  1157. package/dist/icons/generated/shard-02.cjs.map +1 -1
  1158. package/dist/icons/generated/shard-02.js.map +1 -1
  1159. package/dist/icons/generated/shard-03.cjs.map +1 -1
  1160. package/dist/icons/generated/shard-03.js.map +1 -1
  1161. package/dist/icons/generated/shard-04.cjs.map +1 -1
  1162. package/dist/icons/generated/shard-04.js.map +1 -1
  1163. package/dist/icons/generated/shard-05.cjs.map +1 -1
  1164. package/dist/icons/generated/shard-05.js.map +1 -1
  1165. package/dist/icons/generated/shard-06.cjs.map +1 -1
  1166. package/dist/icons/generated/shard-06.js.map +1 -1
  1167. package/dist/icons/generated/shard-07.cjs.map +1 -1
  1168. package/dist/icons/generated/shard-07.js.map +1 -1
  1169. package/dist/icons/generated/shard-08.cjs.map +1 -1
  1170. package/dist/icons/generated/shard-08.js.map +1 -1
  1171. package/dist/icons/generated/shard-09.cjs.map +1 -1
  1172. package/dist/icons/generated/shard-09.js.map +1 -1
  1173. package/dist/icons/generated/shard-10.cjs.map +1 -1
  1174. package/dist/icons/generated/shard-10.js.map +1 -1
  1175. package/dist/icons/generated/shard-11.cjs.map +1 -1
  1176. package/dist/icons/generated/shard-11.js.map +1 -1
  1177. package/dist/icons/generated/shard-12.cjs.map +1 -1
  1178. package/dist/icons/generated/shard-12.js.map +1 -1
  1179. package/dist/icons/generated/shard-13.cjs.map +1 -1
  1180. package/dist/icons/generated/shard-13.js.map +1 -1
  1181. package/dist/icons/generated/shard-14.cjs.map +1 -1
  1182. package/dist/icons/generated/shard-14.js.map +1 -1
  1183. package/dist/icons/generated/shard-15.cjs.map +1 -1
  1184. package/dist/icons/generated/shard-15.js.map +1 -1
  1185. package/dist/icons/generated/shard-16.cjs.map +1 -1
  1186. package/dist/icons/generated/shard-16.js.map +1 -1
  1187. package/dist/icons/generated/shard-17.cjs.map +1 -1
  1188. package/dist/icons/generated/shard-17.js.map +1 -1
  1189. package/dist/icons/generated/shard-18.cjs.map +1 -1
  1190. package/dist/icons/generated/shard-18.js.map +1 -1
  1191. package/dist/icons/generated/shard-19.cjs.map +1 -1
  1192. package/dist/icons/generated/shard-19.js.map +1 -1
  1193. package/dist/icons/generated/shard-20.cjs.map +1 -1
  1194. package/dist/icons/generated/shard-20.js.map +1 -1
  1195. package/dist/icons/generated/shard-21.cjs.map +1 -1
  1196. package/dist/icons/generated/shard-21.js.map +1 -1
  1197. package/dist/icons/generated/shard-22.cjs.map +1 -1
  1198. package/dist/icons/generated/shard-22.js.map +1 -1
  1199. package/dist/icons/generated/shard-23.cjs.map +1 -1
  1200. package/dist/icons/generated/shard-23.js.map +1 -1
  1201. package/dist/icons/generated/shard-24.cjs.map +1 -1
  1202. package/dist/icons/generated/shard-24.js.map +1 -1
  1203. package/dist/icons/generated/shard-25.cjs.map +1 -1
  1204. package/dist/icons/generated/shard-25.js.map +1 -1
  1205. package/dist/icons/generated/shard-26.cjs.map +1 -1
  1206. package/dist/icons/generated/shard-26.js.map +1 -1
  1207. package/dist/icons/generated/shard-27.cjs.map +1 -1
  1208. package/dist/icons/generated/shard-27.js.map +1 -1
  1209. package/dist/icons/generated/shard-28.cjs.map +1 -1
  1210. package/dist/icons/generated/shard-28.js.map +1 -1
  1211. package/dist/icons/generated/shard-29.cjs.map +1 -1
  1212. package/dist/icons/generated/shard-29.js.map +1 -1
  1213. package/dist/icons/generated/shard-30.cjs.map +1 -1
  1214. package/dist/icons/generated/shard-30.js.map +1 -1
  1215. package/dist/icons/generated/shard-31.cjs.map +1 -1
  1216. package/dist/icons/generated/shard-31.js.map +1 -1
  1217. package/dist/icons/generated/shard-32.cjs.map +1 -1
  1218. package/dist/icons/generated/shard-32.js.map +1 -1
  1219. package/dist/icons/generated/shard-33.cjs.map +1 -1
  1220. package/dist/icons/generated/shard-33.js.map +1 -1
  1221. package/dist/icons/generated/shard-34.cjs.map +1 -1
  1222. package/dist/icons/generated/shard-34.js.map +1 -1
  1223. package/dist/icons/generated/shard-35.cjs.map +1 -1
  1224. package/dist/icons/generated/shard-35.js.map +1 -1
  1225. package/dist/icons/generated/shard-36.cjs.map +1 -1
  1226. package/dist/icons/generated/shard-36.js.map +1 -1
  1227. package/dist/icons/generated/shard-37.cjs.map +1 -1
  1228. package/dist/icons/generated/shard-37.js.map +1 -1
  1229. package/dist/icons/generated/shard-38.cjs.map +1 -1
  1230. package/dist/icons/generated/shard-38.js.map +1 -1
  1231. package/dist/icons/generated/shard-39.cjs.map +1 -1
  1232. package/dist/icons/generated/shard-39.js.map +1 -1
  1233. package/dist/icons/generated/shard-40.cjs.map +1 -1
  1234. package/dist/icons/generated/shard-40.js.map +1 -1
  1235. package/dist/icons/generated/shard-41.cjs.map +1 -1
  1236. package/dist/icons/generated/shard-41.js.map +1 -1
  1237. package/dist/icons/generated/shard-42.cjs.map +1 -1
  1238. package/dist/icons/generated/shard-42.js.map +1 -1
  1239. package/dist/icons/generated/shard-43.cjs.map +1 -1
  1240. package/dist/icons/generated/shard-43.js.map +1 -1
  1241. package/dist/icons/generated/shard-44.cjs.map +1 -1
  1242. package/dist/icons/generated/shard-44.js.map +1 -1
  1243. package/dist/icons/generated/shard-45.cjs.map +1 -1
  1244. package/dist/icons/generated/shard-45.js.map +1 -1
  1245. package/dist/icons/icon-context.cjs.map +1 -1
  1246. package/dist/icons/icon-context.js.map +1 -1
  1247. package/dist/icons/is-icon-name.cjs.map +1 -1
  1248. package/dist/icons/is-icon-name.js.map +1 -1
  1249. package/dist/icons/material-symbols.cjs.map +1 -1
  1250. package/dist/icons/material-symbols.js.map +1 -1
  1251. package/dist/icons/normalize-icon-name.cjs.map +1 -1
  1252. package/dist/icons/normalize-icon-name.js.map +1 -1
  1253. package/dist/icons/shard-cache.cjs +1 -1
  1254. package/dist/icons/shard-cache.cjs.map +1 -1
  1255. package/dist/icons/shard-cache.js +2 -5
  1256. package/dist/icons/shard-cache.js.map +1 -1
  1257. package/dist/icons/use-icon.cjs.map +1 -1
  1258. package/dist/icons/use-icon.js.map +1 -1
  1259. package/dist/icons/validate-icon-name.cjs.map +1 -1
  1260. package/dist/icons/validate-icon-name.js.map +1 -1
  1261. package/dist/icons-virtual.cjs.map +1 -1
  1262. package/dist/icons-virtual.js.map +1 -1
  1263. package/dist/imaging/canvas.cjs.map +1 -1
  1264. package/dist/imaging/canvas.js.map +1 -1
  1265. package/dist/imaging/compress.cjs.map +1 -1
  1266. package/dist/imaging/compress.js.map +1 -1
  1267. package/dist/imaging/decode.cjs.map +1 -1
  1268. package/dist/imaging/decode.js.map +1 -1
  1269. package/dist/imaging/encode.cjs.map +1 -1
  1270. package/dist/imaging/encode.js.map +1 -1
  1271. package/dist/imaging/exceptions.cjs.map +1 -1
  1272. package/dist/imaging/exceptions.js.map +1 -1
  1273. package/dist/imaging/frame.cjs.map +1 -1
  1274. package/dist/imaging/frame.js.map +1 -1
  1275. package/dist/imaging/thumbnails.cjs.map +1 -1
  1276. package/dist/imaging/thumbnails.js.map +1 -1
  1277. package/dist/imaging/transform.cjs.map +1 -1
  1278. package/dist/imaging/transform.js.map +1 -1
  1279. package/dist/imaging/use-image-processing.cjs.map +1 -1
  1280. package/dist/imaging/use-image-processing.js.map +1 -1
  1281. package/dist/logger/logger.cjs.map +1 -1
  1282. package/dist/logger/logger.js.map +1 -1
  1283. package/dist/neural.cjs.map +1 -1
  1284. package/dist/neural.js.map +1 -1
  1285. package/dist/oauth/GoogleSignIn.cjs +1 -1
  1286. package/dist/oauth/GoogleSignIn.cjs.map +1 -1
  1287. package/dist/oauth/GoogleSignIn.js +6 -9
  1288. package/dist/oauth/GoogleSignIn.js.map +1 -1
  1289. package/dist/oauth/callback.cjs.map +1 -1
  1290. package/dist/oauth/callback.js.map +1 -1
  1291. package/dist/oauth/use-oauth-callback.cjs.map +1 -1
  1292. package/dist/oauth/use-oauth-callback.js.map +1 -1
  1293. package/dist/offline/conflict.cjs.map +1 -1
  1294. package/dist/offline/conflict.js.map +1 -1
  1295. package/dist/offline/create-offline-database.cjs.map +1 -1
  1296. package/dist/offline/create-offline-database.js.map +1 -1
  1297. package/dist/offline/create-offline-store.cjs +1 -1
  1298. package/dist/offline/create-offline-store.cjs.map +1 -1
  1299. package/dist/offline/create-offline-store.js +1 -5
  1300. package/dist/offline/create-offline-store.js.map +1 -1
  1301. package/dist/offline/create-offline-sync.cjs +1 -1
  1302. package/dist/offline/create-offline-sync.cjs.map +1 -1
  1303. package/dist/offline/create-offline-sync.js +9 -14
  1304. package/dist/offline/create-offline-sync.js.map +1 -1
  1305. package/dist/offline/use-offline-sync.cjs.map +1 -1
  1306. package/dist/offline/use-offline-sync.js.map +1 -1
  1307. package/dist/perf/cache-size.cjs.map +1 -1
  1308. package/dist/perf/cache-size.js.map +1 -1
  1309. package/dist/perf/device.cjs.map +1 -1
  1310. package/dist/perf/device.js.map +1 -1
  1311. package/dist/perf/format.cjs.map +1 -1
  1312. package/dist/perf/format.js.map +1 -1
  1313. package/dist/perf/profiler.cjs.map +1 -1
  1314. package/dist/perf/profiler.js.map +1 -1
  1315. package/dist/push/use-push-subscription.cjs.map +1 -1
  1316. package/dist/push/use-push-subscription.js.map +1 -1
  1317. package/dist/push/utils.cjs.map +1 -1
  1318. package/dist/push/utils.js.map +1 -1
  1319. package/dist/push/web-push-client.cjs.map +1 -1
  1320. package/dist/push/web-push-client.js.map +1 -1
  1321. package/dist/query/QueryProvider.cjs.map +1 -1
  1322. package/dist/query/QueryProvider.js.map +1 -1
  1323. package/dist/query/constants.cjs.map +1 -1
  1324. package/dist/query/constants.js.map +1 -1
  1325. package/dist/query/create-query-keys.cjs.map +1 -1
  1326. package/dist/query/create-query-keys.js.map +1 -1
  1327. package/dist/query/foreign-client-warning.cjs.map +1 -1
  1328. package/dist/query/foreign-client-warning.js.map +1 -1
  1329. package/dist/query/offline-persistence.cjs +1 -1
  1330. package/dist/query/offline-persistence.cjs.map +1 -1
  1331. package/dist/query/offline-persistence.js +2 -10
  1332. package/dist/query/offline-persistence.js.map +1 -1
  1333. package/dist/query/optimistic.cjs.map +1 -1
  1334. package/dist/query/optimistic.js.map +1 -1
  1335. package/dist/query/pagination.cjs.map +1 -1
  1336. package/dist/query/pagination.js.map +1 -1
  1337. package/dist/query/retry-policy.cjs.map +1 -1
  1338. package/dist/query/retry-policy.js.map +1 -1
  1339. package/dist/query/use-cursor-query.cjs.map +1 -1
  1340. package/dist/query/use-cursor-query.js.map +1 -1
  1341. package/dist/query/use-offline-mutation.cjs.map +1 -1
  1342. package/dist/query/use-offline-mutation.js.map +1 -1
  1343. package/dist/query/use-paginated-query.cjs.map +1 -1
  1344. package/dist/query/use-paginated-query.js.map +1 -1
  1345. package/dist/router/AppRouter.cjs.map +1 -1
  1346. package/dist/router/AppRouter.js.map +1 -1
  1347. package/dist/router/RouteGuard.cjs.map +1 -1
  1348. package/dist/router/RouteGuard.js.map +1 -1
  1349. package/dist/router/index.js +2 -2
  1350. package/dist/share/share-or-download.cjs.map +1 -1
  1351. package/dist/share/share-or-download.js.map +1 -1
  1352. package/dist/share/share.cjs.map +1 -1
  1353. package/dist/share/share.js.map +1 -1
  1354. package/dist/sse/create-event-stream.cjs.map +1 -1
  1355. package/dist/sse/create-event-stream.js.map +1 -1
  1356. package/dist/sse/use-event-stream.cjs.map +1 -1
  1357. package/dist/sse/use-event-stream.js.map +1 -1
  1358. package/dist/store/create-selectors.cjs.map +1 -1
  1359. package/dist/store/create-selectors.js.map +1 -1
  1360. package/dist/store/create-store.cjs.map +1 -1
  1361. package/dist/store/create-store.js.map +1 -1
  1362. package/dist/sw/background-sync.cjs +1 -1
  1363. package/dist/sw/background-sync.cjs.map +1 -1
  1364. package/dist/sw/background-sync.js +32 -31
  1365. package/dist/sw/background-sync.js.map +1 -1
  1366. package/dist/sw/cache-inspect.cjs.map +1 -1
  1367. package/dist/sw/cache-inspect.js.map +1 -1
  1368. package/dist/sw/cache.cjs +1 -1
  1369. package/dist/sw/cache.cjs.map +1 -1
  1370. package/dist/sw/cache.js +2 -6
  1371. package/dist/sw/cache.js.map +1 -1
  1372. package/dist/sw/create-push-handler.cjs.map +1 -1
  1373. package/dist/sw/create-push-handler.js.map +1 -1
  1374. package/dist/sw/credential-headers.cjs.map +1 -1
  1375. package/dist/sw/credential-headers.js.map +1 -1
  1376. package/dist/sw/periodic-sync.cjs.map +1 -1
  1377. package/dist/sw/periodic-sync.js.map +1 -1
  1378. package/dist/sw/register-service-worker.cjs.map +1 -1
  1379. package/dist/sw/register-service-worker.js.map +1 -1
  1380. package/dist/sw/session-data.cjs.map +1 -1
  1381. package/dist/sw/session-data.js.map +1 -1
  1382. package/dist/sw.d.ts +46 -8
  1383. package/dist/tabular/assets.cjs.map +1 -1
  1384. package/dist/tabular/assets.js.map +1 -1
  1385. package/dist/tabular/cache.cjs.map +1 -1
  1386. package/dist/tabular/cache.js.map +1 -1
  1387. package/dist/tabular/compact.cjs.map +1 -1
  1388. package/dist/tabular/compact.js.map +1 -1
  1389. package/dist/tabular/exceptions.cjs.map +1 -1
  1390. package/dist/tabular/exceptions.js.map +1 -1
  1391. package/dist/tabular/manifest.cjs.map +1 -1
  1392. package/dist/tabular/manifest.js.map +1 -1
  1393. package/dist/tabular/predictor.cjs.map +1 -1
  1394. package/dist/tabular/predictor.js.map +1 -1
  1395. package/dist/tabular/use-tabular-predictor.cjs.map +1 -1
  1396. package/dist/tabular/use-tabular-predictor.js.map +1 -1
  1397. package/dist/telemetry/TelemetryProvider.cjs.map +1 -1
  1398. package/dist/telemetry/TelemetryProvider.js.map +1 -1
  1399. package/dist/telemetry/app-error-adapter.cjs.map +1 -1
  1400. package/dist/telemetry/app-error-adapter.js.map +1 -1
  1401. package/dist/telemetry/app-error-queue.cjs.map +1 -1
  1402. package/dist/telemetry/app-error-queue.js.map +1 -1
  1403. package/dist/telemetry/app-error-reporter.cjs +1 -1
  1404. package/dist/telemetry/app-error-reporter.cjs.map +1 -1
  1405. package/dist/telemetry/app-error-reporter.js +1 -1
  1406. package/dist/telemetry/app-error-reporter.js.map +1 -1
  1407. package/dist/telemetry/app-error-schema.cjs.map +1 -1
  1408. package/dist/telemetry/app-error-schema.js.map +1 -1
  1409. package/dist/telemetry/app-error-transport.cjs.map +1 -1
  1410. package/dist/telemetry/app-error-transport.js.map +1 -1
  1411. package/dist/telemetry/console-adapter.cjs.map +1 -1
  1412. package/dist/telemetry/console-adapter.js.map +1 -1
  1413. package/dist/telemetry/describe-app-error.cjs.map +1 -1
  1414. package/dist/telemetry/describe-app-error.js.map +1 -1
  1415. package/dist/telemetry/posthog-adapter.cjs +1 -1
  1416. package/dist/telemetry/posthog-adapter.cjs.map +1 -1
  1417. package/dist/telemetry/posthog-adapter.js +1 -5
  1418. package/dist/telemetry/posthog-adapter.js.map +1 -1
  1419. package/dist/telemetry/sentry-adapter.cjs.map +1 -1
  1420. package/dist/telemetry/sentry-adapter.js.map +1 -1
  1421. package/dist/tempest-react-sdk.cjs +1 -1
  1422. package/dist/tempest-react-sdk.d.ts +448 -15
  1423. package/dist/tempest-react-sdk.js +119 -119
  1424. package/dist/testing/create-mock-handlers.cjs.map +1 -1
  1425. package/dist/testing/create-mock-handlers.js.map +1 -1
  1426. package/dist/testing.js +1 -2
  1427. package/dist/theme/ThemeProvider.cjs.map +1 -1
  1428. package/dist/theme/ThemeProvider.js.map +1 -1
  1429. package/dist/theme/apply-theme.cjs.map +1 -1
  1430. package/dist/theme/apply-theme.js.map +1 -1
  1431. package/dist/theme/color.cjs.map +1 -1
  1432. package/dist/theme/color.js.map +1 -1
  1433. package/dist/theme/create-theme.cjs.map +1 -1
  1434. package/dist/theme/create-theme.js.map +1 -1
  1435. package/dist/theme/data-viz-ramps.cjs.map +1 -1
  1436. package/dist/theme/data-viz-ramps.js.map +1 -1
  1437. package/dist/theme/initial-theme.cjs.map +1 -1
  1438. package/dist/theme/initial-theme.js.map +1 -1
  1439. package/dist/theme/inverse-render.cjs.map +1 -1
  1440. package/dist/theme/inverse-render.js.map +1 -1
  1441. package/dist/theme/inverse-restore.cjs.map +1 -1
  1442. package/dist/theme/inverse-restore.js.map +1 -1
  1443. package/dist/theme/inverse-surface.cjs.map +1 -1
  1444. package/dist/theme/inverse-surface.js.map +1 -1
  1445. package/dist/theme/status-tokens.cjs.map +1 -1
  1446. package/dist/theme/status-tokens.js.map +1 -1
  1447. package/dist/theme/theme-presets.cjs.map +1 -1
  1448. package/dist/theme/theme-presets.js.map +1 -1
  1449. package/dist/utils/absent.cjs.map +1 -1
  1450. package/dist/utils/absent.js.map +1 -1
  1451. package/dist/utils/arrays.cjs.map +1 -1
  1452. package/dist/utils/arrays.js.map +1 -1
  1453. package/dist/utils/base64.cjs.map +1 -1
  1454. package/dist/utils/base64.js.map +1 -1
  1455. package/dist/utils/cn.cjs.map +1 -1
  1456. package/dist/utils/cn.js.map +1 -1
  1457. package/dist/utils/compare-values.cjs.map +1 -1
  1458. package/dist/utils/compare-values.js.map +1 -1
  1459. package/dist/utils/compressed-storage.cjs.map +1 -1
  1460. package/dist/utils/compressed-storage.js.map +1 -1
  1461. package/dist/utils/csv.cjs +3 -3
  1462. package/dist/utils/csv.cjs.map +1 -1
  1463. package/dist/utils/csv.js +11 -10
  1464. package/dist/utils/csv.js.map +1 -1
  1465. package/dist/utils/dev-mode.cjs.map +1 -1
  1466. package/dist/utils/dev-mode.js.map +1 -1
  1467. package/dist/utils/duplicate-instance.cjs.map +1 -1
  1468. package/dist/utils/duplicate-instance.js.map +1 -1
  1469. package/dist/utils/format.cjs.map +1 -1
  1470. package/dist/utils/format.js.map +1 -1
  1471. package/dist/utils/functions.cjs +1 -1
  1472. package/dist/utils/functions.cjs.map +1 -1
  1473. package/dist/utils/functions.js +1 -1
  1474. package/dist/utils/functions.js.map +1 -1
  1475. package/dist/utils/guards.cjs.map +1 -1
  1476. package/dist/utils/guards.js.map +1 -1
  1477. package/dist/utils/ids.cjs.map +1 -1
  1478. package/dist/utils/ids.js.map +1 -1
  1479. package/dist/utils/intl-cache.cjs.map +1 -1
  1480. package/dist/utils/intl-cache.js.map +1 -1
  1481. package/dist/utils/json-frame.cjs.map +1 -1
  1482. package/dist/utils/json-frame.js.map +1 -1
  1483. package/dist/utils/numbers.cjs.map +1 -1
  1484. package/dist/utils/numbers.js.map +1 -1
  1485. package/dist/utils/objects.cjs.map +1 -1
  1486. package/dist/utils/objects.js.map +1 -1
  1487. package/dist/{telemetry/app-error-owner.cjs → utils/owner-fingerprint.cjs} +2 -2
  1488. package/dist/utils/owner-fingerprint.cjs.map +1 -0
  1489. package/dist/{telemetry/app-error-owner.js → utils/owner-fingerprint.js} +3 -3
  1490. package/dist/utils/owner-fingerprint.js.map +1 -0
  1491. package/dist/utils/promises.cjs.map +1 -1
  1492. package/dist/utils/promises.js.map +1 -1
  1493. package/dist/utils/relative-time.cjs.map +1 -1
  1494. package/dist/utils/relative-time.js.map +1 -1
  1495. package/dist/utils/safe-url.cjs.map +1 -1
  1496. package/dist/utils/safe-url.js.map +1 -1
  1497. package/dist/utils/schema-like.cjs.map +1 -1
  1498. package/dist/utils/schema-like.js.map +1 -1
  1499. package/dist/utils/storage.cjs +1 -1
  1500. package/dist/utils/storage.cjs.map +1 -1
  1501. package/dist/utils/storage.js +2 -2
  1502. package/dist/utils/storage.js.map +1 -1
  1503. package/dist/utils/strings.cjs.map +1 -1
  1504. package/dist/utils/strings.js.map +1 -1
  1505. package/dist/utils/xlsx.cjs.map +1 -1
  1506. package/dist/utils/xlsx.js.map +1 -1
  1507. package/dist/vision/core/canvas.cjs.map +1 -1
  1508. package/dist/vision/core/canvas.js.map +1 -1
  1509. package/dist/vision/core/dtypes.cjs.map +1 -1
  1510. package/dist/vision/core/dtypes.js.map +1 -1
  1511. package/dist/vision/core/exceptions.cjs.map +1 -1
  1512. package/dist/vision/core/exceptions.js.map +1 -1
  1513. package/dist/vision/core/graph.cjs.map +1 -1
  1514. package/dist/vision/core/graph.js.map +1 -1
  1515. package/dist/vision/core/metadata.cjs +1 -1
  1516. package/dist/vision/core/metadata.cjs.map +1 -1
  1517. package/dist/vision/core/metadata.js +9 -26
  1518. package/dist/vision/core/metadata.js.map +1 -1
  1519. package/dist/vision/core/providers.cjs.map +1 -1
  1520. package/dist/vision/core/providers.js.map +1 -1
  1521. package/dist/vision/core/session.cjs.map +1 -1
  1522. package/dist/vision/core/session.js.map +1 -1
  1523. package/dist/vision/core/timing.cjs.map +1 -1
  1524. package/dist/vision/core/timing.js.map +1 -1
  1525. package/dist/vision/fusion.cjs.map +1 -1
  1526. package/dist/vision/fusion.js.map +1 -1
  1527. package/dist/vision/index.cjs.map +1 -1
  1528. package/dist/vision/index.js.map +1 -1
  1529. package/dist/vision/io/image.cjs.map +1 -1
  1530. package/dist/vision/io/image.js.map +1 -1
  1531. package/dist/vision/labels.cjs.map +1 -1
  1532. package/dist/vision/labels.js.map +1 -1
  1533. package/dist/vision/luminance.cjs.map +1 -1
  1534. package/dist/vision/luminance.js.map +1 -1
  1535. package/dist/vision/normalization.cjs.map +1 -1
  1536. package/dist/vision/normalization.js.map +1 -1
  1537. package/dist/vision/postprocess/classification.cjs.map +1 -1
  1538. package/dist/vision/postprocess/classification.js.map +1 -1
  1539. package/dist/vision/postprocess/detection.cjs.map +1 -1
  1540. package/dist/vision/postprocess/detection.js.map +1 -1
  1541. package/dist/vision/postprocess/segmentation.cjs.map +1 -1
  1542. package/dist/vision/postprocess/segmentation.js.map +1 -1
  1543. package/dist/vision/preprocess/image.cjs.map +1 -1
  1544. package/dist/vision/preprocess/image.js.map +1 -1
  1545. package/dist/vision/preprocess/pipeline.cjs.map +1 -1
  1546. package/dist/vision/preprocess/pipeline.js.map +1 -1
  1547. package/dist/vision/results.cjs.map +1 -1
  1548. package/dist/vision/results.js.map +1 -1
  1549. package/dist/vision/tasks/base.cjs.map +1 -1
  1550. package/dist/vision/tasks/base.js.map +1 -1
  1551. package/dist/vision/tasks/classifier.cjs.map +1 -1
  1552. package/dist/vision/tasks/classifier.js.map +1 -1
  1553. package/dist/vision/tasks/detectClassify.cjs.map +1 -1
  1554. package/dist/vision/tasks/detectClassify.js.map +1 -1
  1555. package/dist/vision/tasks/detector.cjs.map +1 -1
  1556. package/dist/vision/tasks/detector.js.map +1 -1
  1557. package/dist/vision/tasks/segmenter.cjs.map +1 -1
  1558. package/dist/vision/tasks/segmenter.js.map +1 -1
  1559. package/dist/vision/types.cjs.map +1 -1
  1560. package/dist/vision/types.js.map +1 -1
  1561. package/dist/vision/use-camera-stream.cjs +1 -1
  1562. package/dist/vision/use-camera-stream.cjs.map +1 -1
  1563. package/dist/vision/use-camera-stream.js +3 -9
  1564. package/dist/vision/use-camera-stream.js.map +1 -1
  1565. package/dist/vision/use-live-luminance.cjs +1 -1
  1566. package/dist/vision/use-live-luminance.cjs.map +1 -1
  1567. package/dist/vision/use-live-luminance.js +1 -5
  1568. package/dist/vision/use-live-luminance.js.map +1 -1
  1569. package/dist/vite/base-url.cjs.map +1 -1
  1570. package/dist/vite/base-url.js.map +1 -1
  1571. package/dist/vite/create-vite-config.cjs.map +1 -1
  1572. package/dist/vite/create-vite-config.js.map +1 -1
  1573. package/dist/vite/narrow-tokens.cjs.map +1 -1
  1574. package/dist/vite/narrow-tokens.js.map +1 -1
  1575. package/dist/vite/tempest-csp.cjs +2 -2
  1576. package/dist/vite/tempest-csp.cjs.map +1 -1
  1577. package/dist/vite/tempest-csp.js +69 -66
  1578. package/dist/vite/tempest-csp.js.map +1 -1
  1579. package/dist/vite/tempest-icons.cjs.map +1 -1
  1580. package/dist/vite/tempest-icons.js.map +1 -1
  1581. package/dist/vite/tempest-pwa-dev-sw.cjs +1 -1
  1582. package/dist/vite/tempest-pwa-dev-sw.cjs.map +1 -1
  1583. package/dist/vite/tempest-pwa-dev-sw.js +9 -16
  1584. package/dist/vite/tempest-pwa-dev-sw.js.map +1 -1
  1585. package/dist/vite/tempest-pwa-icons.cjs.map +1 -1
  1586. package/dist/vite/tempest-pwa-icons.js.map +1 -1
  1587. package/dist/vite/tempest-pwa-manifest.cjs.map +1 -1
  1588. package/dist/vite/tempest-pwa-manifest.js.map +1 -1
  1589. package/dist/vite/tempest-styles.cjs.map +1 -1
  1590. package/dist/vite/tempest-styles.js.map +1 -1
  1591. package/dist/vite/tempest-vitest.cjs.map +1 -1
  1592. package/dist/vite/tempest-vitest.js.map +1 -1
  1593. package/dist/vite.d.ts +5 -3
  1594. package/dist/webrtc/link-stats.cjs.map +1 -1
  1595. package/dist/webrtc/link-stats.js.map +1 -1
  1596. package/dist/webrtc/mesh-quality.cjs.map +1 -1
  1597. package/dist/webrtc/mesh-quality.js.map +1 -1
  1598. package/dist/webrtc/opus-sdp.cjs.map +1 -1
  1599. package/dist/webrtc/opus-sdp.js.map +1 -1
  1600. package/dist/webrtc/peer-link.cjs +1 -1
  1601. package/dist/webrtc/peer-link.cjs.map +1 -1
  1602. package/dist/webrtc/peer-link.js +2 -5
  1603. package/dist/webrtc/peer-link.js.map +1 -1
  1604. package/dist/webrtc/peer-mesh.cjs +1 -1
  1605. package/dist/webrtc/peer-mesh.cjs.map +1 -1
  1606. package/dist/webrtc/peer-mesh.js +8 -24
  1607. package/dist/webrtc/peer-mesh.js.map +1 -1
  1608. package/dist/webrtc/sender-bitrate.cjs.map +1 -1
  1609. package/dist/webrtc/sender-bitrate.js.map +1 -1
  1610. package/dist/webrtc/use-link-stats.cjs.map +1 -1
  1611. package/dist/webrtc/use-link-stats.js.map +1 -1
  1612. package/dist/ws/create-web-socket.cjs +1 -1
  1613. package/dist/ws/create-web-socket.cjs.map +1 -1
  1614. package/dist/ws/create-web-socket.js +4 -22
  1615. package/dist/ws/create-web-socket.js.map +1 -1
  1616. package/dist/ws/resilience.cjs.map +1 -1
  1617. package/dist/ws/resilience.js.map +1 -1
  1618. package/dist/ws/use-web-socket.cjs.map +1 -1
  1619. package/dist/ws/use-web-socket.js.map +1 -1
  1620. package/package.json +9 -6
  1621. package/template/package.json +1 -1
  1622. package/dist/telemetry/app-error-owner.cjs.map +0 -1
  1623. package/dist/telemetry/app-error-owner.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"FilterBar.module.js","names":[],"sources":["../../../src/components/FilterBar/FilterBar.module.css"],"sourcesContent":[".bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n}\n\n.chips {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-1) var(--tempest-space-1) var(--tempest-space-1)\n var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.empty {\n color: var(--tempest-text-muted);\n}\n\n.remove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: none;\n border-radius: var(--tempest-radius-full);\n background: none;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-base);\n line-height: 1;\n cursor: pointer;\n}\n\n.remove:hover {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text);\n}\n\n/*\n * The editor wraps as a whole on a narrow screen: field, condition and value each\n * keep a usable width instead of shrinking into three unreadable boxes.\n */\n.editor {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n}\n\n.control {\n display: inline-flex;\n min-width: 0;\n}\n\n.select,\n.input {\n min-width: 7rem;\n max-width: 14rem;\n padding: var(--tempest-space-1) var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-bg);\n color: inherit;\n font: inherit;\n}\n\n.select:focus-visible,\n.input:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: calc(var(--tempest-focus-ring-width) * -1);\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n}\n\n.primary,\n.secondary,\n.ghost {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border-radius: var(--tempest-radius-md);\n font: inherit;\n cursor: pointer;\n}\n\n.primary {\n border: none;\n background-color: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n\n.primary:disabled {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.secondary {\n border: 1px dashed var(--tempest-border-strong);\n background-color: transparent;\n color: var(--tempest-text);\n}\n\n.secondary:disabled {\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.ghost {\n border: none;\n background: none;\n color: var(--tempest-text-muted);\n text-decoration: underline;\n}\n\n.primary:focus-visible,\n.secondary:focus-visible,\n.ghost:focus-visible,\n.remove:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: 1px;\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"FilterBar.module.js","names":["bar","chips","chip","empty","remove","editor","control","select","input","actions","primary","secondary","ghost","FilterBar_module_default"],"sources":["../../../src/components/FilterBar/FilterBar.module.css"],"sourcesContent":[".bar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n font-family: var(--tempest-font-sans);\n font-size: var(--tempest-text-sm);\n}\n\n.chips {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n gap: var(--tempest-space-1);\n padding: var(--tempest-space-1) var(--tempest-space-1) var(--tempest-space-1)\n var(--tempest-space-3);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-full);\n background-color: var(--tempest-surface);\n color: var(--tempest-text);\n}\n\n.empty {\n color: var(--tempest-text-muted);\n}\n\n.remove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.25rem;\n height: 1.25rem;\n padding: 0;\n border: none;\n border-radius: var(--tempest-radius-full);\n background: none;\n color: var(--tempest-text-muted);\n font-size: var(--tempest-text-base);\n line-height: 1;\n cursor: pointer;\n}\n\n.remove:hover {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text);\n}\n\n/*\n * The editor wraps as a whole on a narrow screen: field, condition and value each\n * keep a usable width instead of shrinking into three unreadable boxes.\n */\n.editor {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n padding: var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-md);\n background-color: var(--tempest-surface);\n}\n\n.control {\n display: inline-flex;\n min-width: 0;\n}\n\n.select,\n.input {\n min-width: 7rem;\n max-width: 14rem;\n padding: var(--tempest-space-1) var(--tempest-space-2);\n border: 1px solid var(--tempest-border);\n border-radius: var(--tempest-radius-sm);\n background-color: var(--tempest-bg);\n color: inherit;\n font: inherit;\n}\n\n.select:focus-visible,\n.input:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: calc(var(--tempest-focus-ring-width) * -1);\n}\n\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--tempest-space-2);\n}\n\n.primary,\n.secondary,\n.ghost {\n padding: var(--tempest-space-1) var(--tempest-space-3);\n border-radius: var(--tempest-radius-md);\n font: inherit;\n cursor: pointer;\n}\n\n.primary {\n border: none;\n background-color: var(--tempest-primary);\n color: var(--tempest-primary-foreground);\n}\n\n.primary:disabled {\n background-color: var(--tempest-surface-3);\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.secondary {\n border: 1px dashed var(--tempest-border-strong);\n background-color: transparent;\n color: var(--tempest-text);\n}\n\n.secondary:disabled {\n color: var(--tempest-text-subtle);\n cursor: not-allowed;\n}\n\n.ghost {\n border: none;\n background: none;\n color: var(--tempest-text-muted);\n text-decoration: underline;\n}\n\n.primary:focus-visible,\n.secondary:focus-visible,\n.ghost:focus-visible,\n.remove:focus-visible {\n outline: var(--tempest-focus-ring-width) solid var(--tempest-focus-ring-color);\n outline-offset: 1px;\n}\n"],"mappings":";"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-apply.cjs","names":[],"sources":["../../../src/components/FilterBar/filter-apply.ts"],"sourcesContent":["// The other half of the filter model: evaluating a `Filter[]` instead of only\n// describing it. `FilterBar` produces filters, `applyFilters` runs them over an\n// in-memory list, and `filtersToQueryParams` (filter-query.ts) hands the same set\n// to a paginated backend. Without these two the model stops one step short of\n// useful and every app writes the eleven operator branches again.\n\nimport { formatDateForInput } from \"@/utils/format\";\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\n\n/** Matches a plain `yyyy-mm-dd`, the shape `<input type=\"date\">` produces. */\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * One collator for every text comparison in this module.\n *\n * `localeCompare(value, undefined, { numeric: true })` builds a collator on each\n * call — passing an options bag opts out of the engine's cached-default fast\n * path — and this comparison runs once per row per filter. Measured at 200k\n * comparisons: 453 ms through `localeCompare` against 25 ms through a hoisted\n * collator, i.e. ~23 ms of main thread per keystroke on a 10k-row list.\n */\nconst TEXT_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/**\n * Read a property off a row without asserting the row's shape.\n *\n * `Filter.field` is a string chosen by the app's field list, so it cannot be a\n * `keyof T`; the lookup goes through an index signature and a missing property\n * yields `undefined`, which the operators treat as an empty value.\n *\n * @param item - The row being tested.\n * @param field - Property name from the filter.\n * @returns The property value, or `undefined` when the row has no such key.\n */\nfunction readField(item: unknown, field: string): unknown {\n if (item == null || typeof item !== \"object\") return undefined;\n return (item as Record<string, unknown>)[field];\n}\n\n/**\n * Local `yyyy-mm-dd` for a value that represents a date, or `null`.\n *\n * Delegates the formatting to {@link formatDateForInput}, which owns the rule\n * that the key is built from the local calendar parts rather than `toISOString`.\n * This adds only the narrowing from `unknown` and maps \"not a date\" to `null`\n * instead of to the empty string a date input wants.\n *\n * @param value - A `Date`, a date-ish string, or anything else.\n * @returns The day key, or `null` when the value does not denote a date.\n */\nfunction dayKey(value: unknown): string | null {\n if (value instanceof Date) return formatDateForInput(value) || null;\n if (typeof value !== \"string\" || value.trim() === \"\") return null;\n return formatDateForInput(value) || null;\n}\n\n/**\n * Compare a row value against a filter value, in the row value's own type.\n *\n * The filter always carries strings — it comes from form inputs and from the\n * URL — while the row carries whatever the API returned. Comparing them as text\n * gets the two common cases wrong: `10` would sort before `9`, and a date would\n * be compared by however it happens to be formatted. So the row value picks the\n * comparison, and the filter value is coerced into it.\n *\n * Dates compare by **day**, not by instant: a row stamped `2026-03-05T13:00:00Z`\n * is `>= 2026-03-05`, which is what the person picking a date in the UI means.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Negative, zero or positive, or `null` when the two cannot be compared.\n */\nfunction compare(left: unknown, right: string): number | null {\n if (left == null) return null;\n\n if (typeof left === \"number\") {\n const parsed = Number(right);\n return Number.isNaN(parsed) ? null : left - parsed;\n }\n\n if (typeof left === \"boolean\") {\n const parsed = right === \"true\" ? true : right === \"false\" ? false : null;\n return parsed === null ? null : Number(left) - Number(parsed);\n }\n\n if (DATE_ONLY.test(right)) {\n const key = dayKey(left);\n return key === null ? null : key.localeCompare(right);\n }\n\n return TEXT_COLLATOR.compare(String(left), right);\n}\n\n/**\n * Equality in the row value's type, falling back to exact text.\n *\n * Case-sensitive on purpose: `eq` maps to a plain `WHERE column = value` on the\n * server side, so a case-insensitive client would quietly disagree with the\n * backend for the same filter. `contains` is the case-insensitive operator, and\n * it is also the default one for text fields, so the friendly behaviour is what\n * people get without asking.\n *\n * Identical strings take a fast path out, since the row value is text in the\n * common case and the collator is the expensive part.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Whether the two are equal.\n */\nfunction equals(left: unknown, right: string): boolean {\n if (left === right) return true;\n const result = compare(left, right);\n if (result !== null) return result === 0;\n return String(left ?? \"\") === right;\n}\n\n/**\n * Is this row value empty?\n *\n * Empty means absent, blank text or an empty list — never falsy. `0` and `false`\n * are values somebody chose, and a filter that hid them would be reporting the\n * wrong count on every dashboard that tracks zeroes.\n *\n * @param value - The row value.\n * @returns Whether the value counts as empty.\n */\nfunction isEmptyValue(value: unknown): boolean {\n if (value == null) return true;\n if (typeof value === \"string\") return value.trim() === \"\";\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\n/**\n * The filter's value as a list, whatever arity the operator uses.\n *\n * @param filter - The filter to read.\n * @returns Its values, trimmed of nothing — a leading space may be meaningful text.\n */\nfunction valuesOf(filter: Filter): string[] {\n if (filter.value === undefined) return [];\n return Array.isArray(filter.value) ? [...filter.value] : [String(filter.value)];\n}\n\n/**\n * Evaluate one operator against one row value.\n *\n * @param operator - The comparison to make.\n * @param left - The row value.\n * @param values - The filter values (one, two for `between`, many for `in`).\n * @returns Whether the row value satisfies the operator.\n */\nfunction matchesOperator(operator: FilterOperator, left: unknown, values: string[]): boolean {\n switch (operator) {\n case \"empty\":\n return isEmptyValue(left);\n case \"notEmpty\":\n return !isEmptyValue(left);\n case \"eq\":\n return equals(left, values[0] ?? \"\");\n case \"ne\":\n return !equals(left, values[0] ?? \"\");\n case \"contains\":\n return String(left ?? \"\")\n .toLowerCase()\n .includes((values[0] ?? \"\").toLowerCase());\n case \"in\":\n return values.some((value) => equals(left, value));\n case \"between\": {\n const [first = \"\", second = \"\"] = values;\n const low = compare(left, first);\n const high = compare(left, second);\n if (low === null || high === null) return false;\n return low >= 0 && high <= 0;\n }\n default: {\n const result = compare(left, values[0] ?? \"\");\n if (result === null) return false;\n if (operator === \"gt\") return result > 0;\n if (operator === \"gte\") return result >= 0;\n if (operator === \"lt\") return result < 0;\n return result <= 0;\n }\n }\n}\n\n/**\n * Order the two values of a `between` so the range is never empty by accident.\n *\n * A person who picks the later date first means the range between the two dates,\n * not \"no rows\". The server-side `BETWEEN` needs `(lo, hi)` in order too, which\n * is why the normalisation lives here and is shared by `filtersToQueryParams`.\n *\n * @param values - The raw pair.\n * @returns The pair, ascending.\n */\nexport function orderRange(values: readonly string[]): string[] {\n const [first = \"\", second = \"\"] = values;\n if (DATE_ONLY.test(first) && DATE_ONLY.test(second)) {\n return first <= second ? [first, second] : [second, first];\n }\n const low = Number(first);\n const high = Number(second);\n if (!Number.isNaN(low) && !Number.isNaN(high)) {\n return low <= high ? [first, second] : [second, first];\n }\n return TEXT_COLLATOR.compare(first, second) <= 0 ? [first, second] : [second, first];\n}\n\n/**\n * Run a filter set over an in-memory list.\n *\n * Closes the loop `FilterBar` opens: the bar produces `Filter[]`, this applies\n * them. Filters combine with `AND`, matching the flat model the bar builds, and\n * an incomplete filter is skipped rather than treated as a match of nothing — a\n * half-filled form should not empty the table underneath it.\n *\n * Comparison follows the row's type, not the filter's: numbers compare\n * numerically, dates compare by day, and everything else compares as text with\n * `numeric: true` so `\"item 2\"` lands before `\"item 10\"`.\n *\n * A few behaviours differ from the SQL the server-side twin produces, and the\n * difference is deliberate rather than accidental:\n *\n * - `ne` matches rows whose value is absent. In SQL, `column <> 'x'` is `NULL`\n * for a `NULL` column and the row drops out. Here \"is not paid\" shows the rows\n * with no status at all, which is what the chip claims.\n * - `empty` matches `NULL`, blank text and empty lists; `__isnull` on the server\n * only matches `NULL`. A column that stores `\"\"` instead of `NULL` is where\n * the two disagree.\n *\n * @example\n * const visible = applyFilters(orders, filters);\n *\n * Each filter's values are normalised once, before the scan, rather than inside\n * the per-row predicate: the arity, the `between` ordering and the value array\n * depend only on the filter, so deriving them per row multiplied that work by\n * the row count. `empty`/`notEmpty` ignore their values entirely, which is why\n * the prepared shape does not need to distinguish them.\n *\n * @param items - The full list.\n * @param filters - Applied filters; incomplete ones are ignored.\n * @returns A new array with the rows that satisfy every complete filter.\n */\nexport function applyFilters<T>(items: readonly T[], filters: readonly Filter[]): T[] {\n const active = filters.filter(isComplete).map((filter) => ({\n field: filter.field,\n operator: filter.operator,\n values: filter.operator === \"between\" ? orderRange(valuesOf(filter)) : valuesOf(filter),\n }));\n if (active.length === 0) return [...items];\n\n return items.filter((item) =>\n active.every(({ field, operator, values }) =>\n matchesOperator(operator, readField(item, field), values),\n ),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filter-apply.cjs","names":["formatDateForInput","isComplete","require_filter_model","require_format","DATE_ONLY","TEXT_COLLATOR","readField","item","field","dayKey","value","compare","left","parsed","right","key","equals","result","isEmptyValue","valuesOf","filter","matchesOperator","operator","values","first","second","low","high","orderRange","applyFilters","active","filters","items"],"sources":["../../../src/components/FilterBar/filter-apply.ts"],"sourcesContent":["// The other half of the filter model: evaluating a `Filter[]` instead of only\n// describing it. `FilterBar` produces filters, `applyFilters` runs them over an\n// in-memory list, and `filtersToQueryParams` (filter-query.ts) hands the same set\n// to a paginated backend. Without these two the model stops one step short of\n// useful and every app writes the eleven operator branches again.\n\nimport { formatDateForInput } from \"@/utils/format\";\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\n\n/** Matches a plain `yyyy-mm-dd`, the shape `<input type=\"date\">` produces. */\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * One collator for every text comparison in this module.\n *\n * `localeCompare(value, undefined, { numeric: true })` builds a collator on each\n * call — passing an options bag opts out of the engine's cached-default fast\n * path — and this comparison runs once per row per filter. Measured at 200k\n * comparisons: 453 ms through `localeCompare` against 25 ms through a hoisted\n * collator, i.e. ~23 ms of main thread per keystroke on a 10k-row list.\n */\nconst TEXT_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/**\n * Read a property off a row without asserting the row's shape.\n *\n * `Filter.field` is a string chosen by the app's field list, so it cannot be a\n * `keyof T`; the lookup goes through an index signature and a missing property\n * yields `undefined`, which the operators treat as an empty value.\n *\n * @param item - The row being tested.\n * @param field - Property name from the filter.\n * @returns The property value, or `undefined` when the row has no such key.\n */\nfunction readField(item: unknown, field: string): unknown {\n if (item == null || typeof item !== \"object\") return undefined;\n return (item as Record<string, unknown>)[field];\n}\n\n/**\n * Local `yyyy-mm-dd` for a value that represents a date, or `null`.\n *\n * Delegates the formatting to {@link formatDateForInput}, which owns the rule\n * that the key is built from the local calendar parts rather than `toISOString`.\n * This adds only the narrowing from `unknown` and maps \"not a date\" to `null`\n * instead of to the empty string a date input wants.\n *\n * @param value - A `Date`, a date-ish string, or anything else.\n * @returns The day key, or `null` when the value does not denote a date.\n */\nfunction dayKey(value: unknown): string | null {\n if (value instanceof Date) return formatDateForInput(value) || null;\n if (typeof value !== \"string\" || value.trim() === \"\") return null;\n return formatDateForInput(value) || null;\n}\n\n/**\n * Compare a row value against a filter value, in the row value's own type.\n *\n * The filter always carries strings — it comes from form inputs and from the\n * URL — while the row carries whatever the API returned. Comparing them as text\n * gets the two common cases wrong: `10` would sort before `9`, and a date would\n * be compared by however it happens to be formatted. So the row value picks the\n * comparison, and the filter value is coerced into it.\n *\n * Dates compare by **day**, not by instant: a row stamped `2026-03-05T13:00:00Z`\n * is `>= 2026-03-05`, which is what the person picking a date in the UI means.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Negative, zero or positive, or `null` when the two cannot be compared.\n */\nfunction compare(left: unknown, right: string): number | null {\n if (left == null) return null;\n\n if (typeof left === \"number\") {\n const parsed = Number(right);\n return Number.isNaN(parsed) ? null : left - parsed;\n }\n\n if (typeof left === \"boolean\") {\n const parsed = right === \"true\" ? true : right === \"false\" ? false : null;\n return parsed === null ? null : Number(left) - Number(parsed);\n }\n\n if (DATE_ONLY.test(right)) {\n const key = dayKey(left);\n return key === null ? null : key.localeCompare(right);\n }\n\n return TEXT_COLLATOR.compare(String(left), right);\n}\n\n/**\n * Equality in the row value's type, falling back to exact text.\n *\n * Case-sensitive on purpose: `eq` maps to a plain `WHERE column = value` on the\n * server side, so a case-insensitive client would quietly disagree with the\n * backend for the same filter. `contains` is the case-insensitive operator, and\n * it is also the default one for text fields, so the friendly behaviour is what\n * people get without asking.\n *\n * Identical strings take a fast path out, since the row value is text in the\n * common case and the collator is the expensive part.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Whether the two are equal.\n */\nfunction equals(left: unknown, right: string): boolean {\n if (left === right) return true;\n const result = compare(left, right);\n if (result !== null) return result === 0;\n return String(left ?? \"\") === right;\n}\n\n/**\n * Is this row value empty?\n *\n * Empty means absent, blank text or an empty list — never falsy. `0` and `false`\n * are values somebody chose, and a filter that hid them would be reporting the\n * wrong count on every dashboard that tracks zeroes.\n *\n * @param value - The row value.\n * @returns Whether the value counts as empty.\n */\nfunction isEmptyValue(value: unknown): boolean {\n if (value == null) return true;\n if (typeof value === \"string\") return value.trim() === \"\";\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\n/**\n * The filter's value as a list, whatever arity the operator uses.\n *\n * @param filter - The filter to read.\n * @returns Its values, trimmed of nothing — a leading space may be meaningful text.\n */\nfunction valuesOf(filter: Filter): string[] {\n if (filter.value === undefined) return [];\n return Array.isArray(filter.value) ? [...filter.value] : [String(filter.value)];\n}\n\n/**\n * Evaluate one operator against one row value.\n *\n * @param operator - The comparison to make.\n * @param left - The row value.\n * @param values - The filter values (one, two for `between`, many for `in`).\n * @returns Whether the row value satisfies the operator.\n */\nfunction matchesOperator(operator: FilterOperator, left: unknown, values: string[]): boolean {\n switch (operator) {\n case \"empty\":\n return isEmptyValue(left);\n case \"notEmpty\":\n return !isEmptyValue(left);\n case \"eq\":\n return equals(left, values[0] ?? \"\");\n case \"ne\":\n return !equals(left, values[0] ?? \"\");\n case \"contains\":\n return String(left ?? \"\")\n .toLowerCase()\n .includes((values[0] ?? \"\").toLowerCase());\n case \"in\":\n return values.some((value) => equals(left, value));\n case \"between\": {\n const [first = \"\", second = \"\"] = values;\n const low = compare(left, first);\n const high = compare(left, second);\n if (low === null || high === null) return false;\n return low >= 0 && high <= 0;\n }\n default: {\n const result = compare(left, values[0] ?? \"\");\n if (result === null) return false;\n if (operator === \"gt\") return result > 0;\n if (operator === \"gte\") return result >= 0;\n if (operator === \"lt\") return result < 0;\n return result <= 0;\n }\n }\n}\n\n/**\n * Order the two values of a `between` so the range is never empty by accident.\n *\n * A person who picks the later date first means the range between the two dates,\n * not \"no rows\". The server-side `BETWEEN` needs `(lo, hi)` in order too, which\n * is why the normalisation lives here and is shared by `filtersToQueryParams`.\n *\n * @param values - The raw pair.\n * @returns The pair, ascending.\n */\nexport function orderRange(values: readonly string[]): string[] {\n const [first = \"\", second = \"\"] = values;\n if (DATE_ONLY.test(first) && DATE_ONLY.test(second)) {\n return first <= second ? [first, second] : [second, first];\n }\n const low = Number(first);\n const high = Number(second);\n if (!Number.isNaN(low) && !Number.isNaN(high)) {\n return low <= high ? [first, second] : [second, first];\n }\n return TEXT_COLLATOR.compare(first, second) <= 0 ? [first, second] : [second, first];\n}\n\n/**\n * Run a filter set over an in-memory list.\n *\n * Closes the loop `FilterBar` opens: the bar produces `Filter[]`, this applies\n * them. Filters combine with `AND`, matching the flat model the bar builds, and\n * an incomplete filter is skipped rather than treated as a match of nothing — a\n * half-filled form should not empty the table underneath it.\n *\n * Comparison follows the row's type, not the filter's: numbers compare\n * numerically, dates compare by day, and everything else compares as text with\n * `numeric: true` so `\"item 2\"` lands before `\"item 10\"`.\n *\n * A few behaviours differ from the SQL the server-side twin produces, and the\n * difference is deliberate rather than accidental:\n *\n * - `ne` matches rows whose value is absent. In SQL, `column <> 'x'` is `NULL`\n * for a `NULL` column and the row drops out. Here \"is not paid\" shows the rows\n * with no status at all, which is what the chip claims.\n * - `empty` matches `NULL`, blank text and empty lists; `__isnull` on the server\n * only matches `NULL`. A column that stores `\"\"` instead of `NULL` is where\n * the two disagree.\n *\n * @example\n * const visible = applyFilters(orders, filters);\n *\n * Each filter's values are normalised once, before the scan, rather than inside\n * the per-row predicate: the arity, the `between` ordering and the value array\n * depend only on the filter, so deriving them per row multiplied that work by\n * the row count. `empty`/`notEmpty` ignore their values entirely, which is why\n * the prepared shape does not need to distinguish them.\n *\n * @param items - The full list.\n * @param filters - Applied filters; incomplete ones are ignored.\n * @returns A new array with the rows that satisfy every complete filter.\n */\nexport function applyFilters<T>(items: readonly T[], filters: readonly Filter[]): T[] {\n const active = filters.filter(isComplete).map((filter) => ({\n field: filter.field,\n operator: filter.operator,\n values: filter.operator === \"between\" ? orderRange(valuesOf(filter)) : valuesOf(filter),\n }));\n if (active.length === 0) return [...items];\n\n return items.filter((item) =>\n active.every(({ field, operator, values }) =>\n matchesOperator(operator, readField(item, field), values),\n ),\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-apply.js","names":[],"sources":["../../../src/components/FilterBar/filter-apply.ts"],"sourcesContent":["// The other half of the filter model: evaluating a `Filter[]` instead of only\n// describing it. `FilterBar` produces filters, `applyFilters` runs them over an\n// in-memory list, and `filtersToQueryParams` (filter-query.ts) hands the same set\n// to a paginated backend. Without these two the model stops one step short of\n// useful and every app writes the eleven operator branches again.\n\nimport { formatDateForInput } from \"@/utils/format\";\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\n\n/** Matches a plain `yyyy-mm-dd`, the shape `<input type=\"date\">` produces. */\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * One collator for every text comparison in this module.\n *\n * `localeCompare(value, undefined, { numeric: true })` builds a collator on each\n * call — passing an options bag opts out of the engine's cached-default fast\n * path — and this comparison runs once per row per filter. Measured at 200k\n * comparisons: 453 ms through `localeCompare` against 25 ms through a hoisted\n * collator, i.e. ~23 ms of main thread per keystroke on a 10k-row list.\n */\nconst TEXT_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/**\n * Read a property off a row without asserting the row's shape.\n *\n * `Filter.field` is a string chosen by the app's field list, so it cannot be a\n * `keyof T`; the lookup goes through an index signature and a missing property\n * yields `undefined`, which the operators treat as an empty value.\n *\n * @param item - The row being tested.\n * @param field - Property name from the filter.\n * @returns The property value, or `undefined` when the row has no such key.\n */\nfunction readField(item: unknown, field: string): unknown {\n if (item == null || typeof item !== \"object\") return undefined;\n return (item as Record<string, unknown>)[field];\n}\n\n/**\n * Local `yyyy-mm-dd` for a value that represents a date, or `null`.\n *\n * Delegates the formatting to {@link formatDateForInput}, which owns the rule\n * that the key is built from the local calendar parts rather than `toISOString`.\n * This adds only the narrowing from `unknown` and maps \"not a date\" to `null`\n * instead of to the empty string a date input wants.\n *\n * @param value - A `Date`, a date-ish string, or anything else.\n * @returns The day key, or `null` when the value does not denote a date.\n */\nfunction dayKey(value: unknown): string | null {\n if (value instanceof Date) return formatDateForInput(value) || null;\n if (typeof value !== \"string\" || value.trim() === \"\") return null;\n return formatDateForInput(value) || null;\n}\n\n/**\n * Compare a row value against a filter value, in the row value's own type.\n *\n * The filter always carries strings — it comes from form inputs and from the\n * URL — while the row carries whatever the API returned. Comparing them as text\n * gets the two common cases wrong: `10` would sort before `9`, and a date would\n * be compared by however it happens to be formatted. So the row value picks the\n * comparison, and the filter value is coerced into it.\n *\n * Dates compare by **day**, not by instant: a row stamped `2026-03-05T13:00:00Z`\n * is `>= 2026-03-05`, which is what the person picking a date in the UI means.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Negative, zero or positive, or `null` when the two cannot be compared.\n */\nfunction compare(left: unknown, right: string): number | null {\n if (left == null) return null;\n\n if (typeof left === \"number\") {\n const parsed = Number(right);\n return Number.isNaN(parsed) ? null : left - parsed;\n }\n\n if (typeof left === \"boolean\") {\n const parsed = right === \"true\" ? true : right === \"false\" ? false : null;\n return parsed === null ? null : Number(left) - Number(parsed);\n }\n\n if (DATE_ONLY.test(right)) {\n const key = dayKey(left);\n return key === null ? null : key.localeCompare(right);\n }\n\n return TEXT_COLLATOR.compare(String(left), right);\n}\n\n/**\n * Equality in the row value's type, falling back to exact text.\n *\n * Case-sensitive on purpose: `eq` maps to a plain `WHERE column = value` on the\n * server side, so a case-insensitive client would quietly disagree with the\n * backend for the same filter. `contains` is the case-insensitive operator, and\n * it is also the default one for text fields, so the friendly behaviour is what\n * people get without asking.\n *\n * Identical strings take a fast path out, since the row value is text in the\n * common case and the collator is the expensive part.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Whether the two are equal.\n */\nfunction equals(left: unknown, right: string): boolean {\n if (left === right) return true;\n const result = compare(left, right);\n if (result !== null) return result === 0;\n return String(left ?? \"\") === right;\n}\n\n/**\n * Is this row value empty?\n *\n * Empty means absent, blank text or an empty list — never falsy. `0` and `false`\n * are values somebody chose, and a filter that hid them would be reporting the\n * wrong count on every dashboard that tracks zeroes.\n *\n * @param value - The row value.\n * @returns Whether the value counts as empty.\n */\nfunction isEmptyValue(value: unknown): boolean {\n if (value == null) return true;\n if (typeof value === \"string\") return value.trim() === \"\";\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\n/**\n * The filter's value as a list, whatever arity the operator uses.\n *\n * @param filter - The filter to read.\n * @returns Its values, trimmed of nothing — a leading space may be meaningful text.\n */\nfunction valuesOf(filter: Filter): string[] {\n if (filter.value === undefined) return [];\n return Array.isArray(filter.value) ? [...filter.value] : [String(filter.value)];\n}\n\n/**\n * Evaluate one operator against one row value.\n *\n * @param operator - The comparison to make.\n * @param left - The row value.\n * @param values - The filter values (one, two for `between`, many for `in`).\n * @returns Whether the row value satisfies the operator.\n */\nfunction matchesOperator(operator: FilterOperator, left: unknown, values: string[]): boolean {\n switch (operator) {\n case \"empty\":\n return isEmptyValue(left);\n case \"notEmpty\":\n return !isEmptyValue(left);\n case \"eq\":\n return equals(left, values[0] ?? \"\");\n case \"ne\":\n return !equals(left, values[0] ?? \"\");\n case \"contains\":\n return String(left ?? \"\")\n .toLowerCase()\n .includes((values[0] ?? \"\").toLowerCase());\n case \"in\":\n return values.some((value) => equals(left, value));\n case \"between\": {\n const [first = \"\", second = \"\"] = values;\n const low = compare(left, first);\n const high = compare(left, second);\n if (low === null || high === null) return false;\n return low >= 0 && high <= 0;\n }\n default: {\n const result = compare(left, values[0] ?? \"\");\n if (result === null) return false;\n if (operator === \"gt\") return result > 0;\n if (operator === \"gte\") return result >= 0;\n if (operator === \"lt\") return result < 0;\n return result <= 0;\n }\n }\n}\n\n/**\n * Order the two values of a `between` so the range is never empty by accident.\n *\n * A person who picks the later date first means the range between the two dates,\n * not \"no rows\". The server-side `BETWEEN` needs `(lo, hi)` in order too, which\n * is why the normalisation lives here and is shared by `filtersToQueryParams`.\n *\n * @param values - The raw pair.\n * @returns The pair, ascending.\n */\nexport function orderRange(values: readonly string[]): string[] {\n const [first = \"\", second = \"\"] = values;\n if (DATE_ONLY.test(first) && DATE_ONLY.test(second)) {\n return first <= second ? [first, second] : [second, first];\n }\n const low = Number(first);\n const high = Number(second);\n if (!Number.isNaN(low) && !Number.isNaN(high)) {\n return low <= high ? [first, second] : [second, first];\n }\n return TEXT_COLLATOR.compare(first, second) <= 0 ? [first, second] : [second, first];\n}\n\n/**\n * Run a filter set over an in-memory list.\n *\n * Closes the loop `FilterBar` opens: the bar produces `Filter[]`, this applies\n * them. Filters combine with `AND`, matching the flat model the bar builds, and\n * an incomplete filter is skipped rather than treated as a match of nothing — a\n * half-filled form should not empty the table underneath it.\n *\n * Comparison follows the row's type, not the filter's: numbers compare\n * numerically, dates compare by day, and everything else compares as text with\n * `numeric: true` so `\"item 2\"` lands before `\"item 10\"`.\n *\n * A few behaviours differ from the SQL the server-side twin produces, and the\n * difference is deliberate rather than accidental:\n *\n * - `ne` matches rows whose value is absent. In SQL, `column <> 'x'` is `NULL`\n * for a `NULL` column and the row drops out. Here \"is not paid\" shows the rows\n * with no status at all, which is what the chip claims.\n * - `empty` matches `NULL`, blank text and empty lists; `__isnull` on the server\n * only matches `NULL`. A column that stores `\"\"` instead of `NULL` is where\n * the two disagree.\n *\n * @example\n * const visible = applyFilters(orders, filters);\n *\n * Each filter's values are normalised once, before the scan, rather than inside\n * the per-row predicate: the arity, the `between` ordering and the value array\n * depend only on the filter, so deriving them per row multiplied that work by\n * the row count. `empty`/`notEmpty` ignore their values entirely, which is why\n * the prepared shape does not need to distinguish them.\n *\n * @param items - The full list.\n * @param filters - Applied filters; incomplete ones are ignored.\n * @returns A new array with the rows that satisfy every complete filter.\n */\nexport function applyFilters<T>(items: readonly T[], filters: readonly Filter[]): T[] {\n const active = filters.filter(isComplete).map((filter) => ({\n field: filter.field,\n operator: filter.operator,\n values: filter.operator === \"between\" ? orderRange(valuesOf(filter)) : valuesOf(filter),\n }));\n if (active.length === 0) return [...items];\n\n return items.filter((item) =>\n active.every(({ field, operator, values }) =>\n matchesOperator(operator, readField(item, field), values),\n ),\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filter-apply.js","names":["DATE_ONLY","TEXT_COLLATOR","readField","item","field","dayKey","value","formatDateForInput","compare","left","parsed","right","key","equals","result","isEmptyValue","valuesOf","filter","matchesOperator","operator","values","first","second","low","high","orderRange","applyFilters","active","filters","isComplete","items"],"sources":["../../../src/components/FilterBar/filter-apply.ts"],"sourcesContent":["// The other half of the filter model: evaluating a `Filter[]` instead of only\n// describing it. `FilterBar` produces filters, `applyFilters` runs them over an\n// in-memory list, and `filtersToQueryParams` (filter-query.ts) hands the same set\n// to a paginated backend. Without these two the model stops one step short of\n// useful and every app writes the eleven operator branches again.\n\nimport { formatDateForInput } from \"@/utils/format\";\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\n\n/** Matches a plain `yyyy-mm-dd`, the shape `<input type=\"date\">` produces. */\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * One collator for every text comparison in this module.\n *\n * `localeCompare(value, undefined, { numeric: true })` builds a collator on each\n * call — passing an options bag opts out of the engine's cached-default fast\n * path — and this comparison runs once per row per filter. Measured at 200k\n * comparisons: 453 ms through `localeCompare` against 25 ms through a hoisted\n * collator, i.e. ~23 ms of main thread per keystroke on a 10k-row list.\n */\nconst TEXT_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/**\n * Read a property off a row without asserting the row's shape.\n *\n * `Filter.field` is a string chosen by the app's field list, so it cannot be a\n * `keyof T`; the lookup goes through an index signature and a missing property\n * yields `undefined`, which the operators treat as an empty value.\n *\n * @param item - The row being tested.\n * @param field - Property name from the filter.\n * @returns The property value, or `undefined` when the row has no such key.\n */\nfunction readField(item: unknown, field: string): unknown {\n if (item == null || typeof item !== \"object\") return undefined;\n return (item as Record<string, unknown>)[field];\n}\n\n/**\n * Local `yyyy-mm-dd` for a value that represents a date, or `null`.\n *\n * Delegates the formatting to {@link formatDateForInput}, which owns the rule\n * that the key is built from the local calendar parts rather than `toISOString`.\n * This adds only the narrowing from `unknown` and maps \"not a date\" to `null`\n * instead of to the empty string a date input wants.\n *\n * @param value - A `Date`, a date-ish string, or anything else.\n * @returns The day key, or `null` when the value does not denote a date.\n */\nfunction dayKey(value: unknown): string | null {\n if (value instanceof Date) return formatDateForInput(value) || null;\n if (typeof value !== \"string\" || value.trim() === \"\") return null;\n return formatDateForInput(value) || null;\n}\n\n/**\n * Compare a row value against a filter value, in the row value's own type.\n *\n * The filter always carries strings — it comes from form inputs and from the\n * URL — while the row carries whatever the API returned. Comparing them as text\n * gets the two common cases wrong: `10` would sort before `9`, and a date would\n * be compared by however it happens to be formatted. So the row value picks the\n * comparison, and the filter value is coerced into it.\n *\n * Dates compare by **day**, not by instant: a row stamped `2026-03-05T13:00:00Z`\n * is `>= 2026-03-05`, which is what the person picking a date in the UI means.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Negative, zero or positive, or `null` when the two cannot be compared.\n */\nfunction compare(left: unknown, right: string): number | null {\n if (left == null) return null;\n\n if (typeof left === \"number\") {\n const parsed = Number(right);\n return Number.isNaN(parsed) ? null : left - parsed;\n }\n\n if (typeof left === \"boolean\") {\n const parsed = right === \"true\" ? true : right === \"false\" ? false : null;\n return parsed === null ? null : Number(left) - Number(parsed);\n }\n\n if (DATE_ONLY.test(right)) {\n const key = dayKey(left);\n return key === null ? null : key.localeCompare(right);\n }\n\n return TEXT_COLLATOR.compare(String(left), right);\n}\n\n/**\n * Equality in the row value's type, falling back to exact text.\n *\n * Case-sensitive on purpose: `eq` maps to a plain `WHERE column = value` on the\n * server side, so a case-insensitive client would quietly disagree with the\n * backend for the same filter. `contains` is the case-insensitive operator, and\n * it is also the default one for text fields, so the friendly behaviour is what\n * people get without asking.\n *\n * Identical strings take a fast path out, since the row value is text in the\n * common case and the collator is the expensive part.\n *\n * @param left - The row value.\n * @param right - The raw filter value.\n * @returns Whether the two are equal.\n */\nfunction equals(left: unknown, right: string): boolean {\n if (left === right) return true;\n const result = compare(left, right);\n if (result !== null) return result === 0;\n return String(left ?? \"\") === right;\n}\n\n/**\n * Is this row value empty?\n *\n * Empty means absent, blank text or an empty list — never falsy. `0` and `false`\n * are values somebody chose, and a filter that hid them would be reporting the\n * wrong count on every dashboard that tracks zeroes.\n *\n * @param value - The row value.\n * @returns Whether the value counts as empty.\n */\nfunction isEmptyValue(value: unknown): boolean {\n if (value == null) return true;\n if (typeof value === \"string\") return value.trim() === \"\";\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\n/**\n * The filter's value as a list, whatever arity the operator uses.\n *\n * @param filter - The filter to read.\n * @returns Its values, trimmed of nothing — a leading space may be meaningful text.\n */\nfunction valuesOf(filter: Filter): string[] {\n if (filter.value === undefined) return [];\n return Array.isArray(filter.value) ? [...filter.value] : [String(filter.value)];\n}\n\n/**\n * Evaluate one operator against one row value.\n *\n * @param operator - The comparison to make.\n * @param left - The row value.\n * @param values - The filter values (one, two for `between`, many for `in`).\n * @returns Whether the row value satisfies the operator.\n */\nfunction matchesOperator(operator: FilterOperator, left: unknown, values: string[]): boolean {\n switch (operator) {\n case \"empty\":\n return isEmptyValue(left);\n case \"notEmpty\":\n return !isEmptyValue(left);\n case \"eq\":\n return equals(left, values[0] ?? \"\");\n case \"ne\":\n return !equals(left, values[0] ?? \"\");\n case \"contains\":\n return String(left ?? \"\")\n .toLowerCase()\n .includes((values[0] ?? \"\").toLowerCase());\n case \"in\":\n return values.some((value) => equals(left, value));\n case \"between\": {\n const [first = \"\", second = \"\"] = values;\n const low = compare(left, first);\n const high = compare(left, second);\n if (low === null || high === null) return false;\n return low >= 0 && high <= 0;\n }\n default: {\n const result = compare(left, values[0] ?? \"\");\n if (result === null) return false;\n if (operator === \"gt\") return result > 0;\n if (operator === \"gte\") return result >= 0;\n if (operator === \"lt\") return result < 0;\n return result <= 0;\n }\n }\n}\n\n/**\n * Order the two values of a `between` so the range is never empty by accident.\n *\n * A person who picks the later date first means the range between the two dates,\n * not \"no rows\". The server-side `BETWEEN` needs `(lo, hi)` in order too, which\n * is why the normalisation lives here and is shared by `filtersToQueryParams`.\n *\n * @param values - The raw pair.\n * @returns The pair, ascending.\n */\nexport function orderRange(values: readonly string[]): string[] {\n const [first = \"\", second = \"\"] = values;\n if (DATE_ONLY.test(first) && DATE_ONLY.test(second)) {\n return first <= second ? [first, second] : [second, first];\n }\n const low = Number(first);\n const high = Number(second);\n if (!Number.isNaN(low) && !Number.isNaN(high)) {\n return low <= high ? [first, second] : [second, first];\n }\n return TEXT_COLLATOR.compare(first, second) <= 0 ? [first, second] : [second, first];\n}\n\n/**\n * Run a filter set over an in-memory list.\n *\n * Closes the loop `FilterBar` opens: the bar produces `Filter[]`, this applies\n * them. Filters combine with `AND`, matching the flat model the bar builds, and\n * an incomplete filter is skipped rather than treated as a match of nothing — a\n * half-filled form should not empty the table underneath it.\n *\n * Comparison follows the row's type, not the filter's: numbers compare\n * numerically, dates compare by day, and everything else compares as text with\n * `numeric: true` so `\"item 2\"` lands before `\"item 10\"`.\n *\n * A few behaviours differ from the SQL the server-side twin produces, and the\n * difference is deliberate rather than accidental:\n *\n * - `ne` matches rows whose value is absent. In SQL, `column <> 'x'` is `NULL`\n * for a `NULL` column and the row drops out. Here \"is not paid\" shows the rows\n * with no status at all, which is what the chip claims.\n * - `empty` matches `NULL`, blank text and empty lists; `__isnull` on the server\n * only matches `NULL`. A column that stores `\"\"` instead of `NULL` is where\n * the two disagree.\n *\n * @example\n * const visible = applyFilters(orders, filters);\n *\n * Each filter's values are normalised once, before the scan, rather than inside\n * the per-row predicate: the arity, the `between` ordering and the value array\n * depend only on the filter, so deriving them per row multiplied that work by\n * the row count. `empty`/`notEmpty` ignore their values entirely, which is why\n * the prepared shape does not need to distinguish them.\n *\n * @param items - The full list.\n * @param filters - Applied filters; incomplete ones are ignored.\n * @returns A new array with the rows that satisfy every complete filter.\n */\nexport function applyFilters<T>(items: readonly T[], filters: readonly Filter[]): T[] {\n const active = filters.filter(isComplete).map((filter) => ({\n field: filter.field,\n operator: filter.operator,\n values: filter.operator === \"between\" ? orderRange(valuesOf(filter)) : valuesOf(filter),\n }));\n if (active.length === 0) return [...items];\n\n return items.filter((item) =>\n active.every(({ field, operator, values }) =>\n matchesOperator(operator, readField(item, field), values),\n ),\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-model.cjs","names":[],"sources":["../../../src/components/FilterBar/filter-model.ts"],"sourcesContent":["// The filter model behind `FilterBar`: what a field can be compared with, how a\n// filter reads in words, and how a filter set survives a page reload.\n//\n// Flat AND, deliberately. Nested `(a OR b) AND c` groups are a different component\n// with a different UI (a tree with per-node operators) and a different serialization\n// — trying to be both produces a builder that is clumsy for the 95% case, which is\n// \"status is paid, created after March, text contains nota\".\n\n/** Comparison a filter can make. */\nexport type FilterOperator =\n | \"eq\"\n | \"ne\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\"\n | \"in\"\n | \"empty\"\n | \"notEmpty\";\n\n/** Kind of value a field holds, which decides its operators and its input. */\nexport type FilterFieldType = \"text\" | \"number\" | \"date\" | \"select\" | \"boolean\";\n\n/** One filterable field. */\nexport interface FilterField {\n /** Key sent to the backend. */\n name: string;\n /** What the user sees. */\n label: string;\n type: FilterFieldType;\n /** Choices for `select`. */\n options?: ReadonlyArray<{ value: string; label: string }>;\n /** Restrict or reorder the operators offered. Defaults per type. */\n operators?: readonly FilterOperator[];\n /** Placeholder for the value input. */\n placeholder?: string;\n}\n\n/** One applied filter. */\nexport interface Filter {\n field: string;\n operator: FilterOperator;\n /** `between` carries a pair; `in` carries a list; `empty`/`notEmpty` carry nothing. */\n value?: string | readonly string[];\n}\n\n/** Operators offered per field type, in the order they appear. */\nconst OPERATORS_BY_TYPE: Record<FilterFieldType, FilterOperator[]> = {\n text: [\"contains\", \"eq\", \"ne\", \"empty\", \"notEmpty\"],\n number: [\"eq\", \"ne\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n date: [\"eq\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n select: [\"eq\", \"ne\", \"in\", \"empty\", \"notEmpty\"],\n boolean: [\"eq\"],\n};\n\n/** Operators that take no value at all. */\nconst VALUELESS: ReadonlySet<FilterOperator> = new Set([\"empty\", \"notEmpty\"]);\n\n/** Operators that take more than one value. */\nconst MULTI: ReadonlySet<FilterOperator> = new Set([\"between\", \"in\"]);\n\n/** Human labels for the operators, per locale. */\nconst OPERATOR_LABELS: Record<\"pt-BR\" | \"en\", Record<FilterOperator, string>> = {\n \"pt-BR\": {\n eq: \"é\",\n ne: \"não é\",\n contains: \"contém\",\n gt: \"maior que\",\n gte: \"maior ou igual a\",\n lt: \"menor que\",\n lte: \"menor ou igual a\",\n between: \"entre\",\n in: \"é um de\",\n empty: \"está vazio\",\n notEmpty: \"não está vazio\",\n },\n en: {\n eq: \"is\",\n ne: \"is not\",\n contains: \"contains\",\n gt: \"greater than\",\n gte: \"at least\",\n lt: \"less than\",\n lte: \"at most\",\n between: \"between\",\n in: \"is any of\",\n empty: \"is empty\",\n notEmpty: \"is not empty\",\n },\n};\n\n/** The operators a field offers. */\nexport function operatorsFor(field: FilterField): FilterOperator[] {\n return [...(field.operators ?? OPERATORS_BY_TYPE[field.type])];\n}\n\n/** Label of an operator. */\nexport function operatorLabel(operator: FilterOperator, locale: \"pt-BR\" | \"en\" = \"pt-BR\"): string {\n return OPERATOR_LABELS[locale][operator] ?? operator;\n}\n\n/** True when the operator needs no value input. */\nexport function isValueless(operator: FilterOperator): boolean {\n return VALUELESS.has(operator);\n}\n\n/** True when the operator takes several values. */\nexport function isMulti(operator: FilterOperator): boolean {\n return MULTI.has(operator);\n}\n\n/**\n * Is this filter complete enough to apply?\n *\n * An incomplete filter is not an error to shout about — it is a half-filled form.\n * The component uses this to keep \"Add\" disabled, which says the same thing without\n * a message nobody asked for.\n */\nexport function isComplete(filter: Filter): boolean {\n if (isValueless(filter.operator)) return true;\n const { value } = filter;\n if (value === undefined) return false;\n if (Array.isArray(value)) {\n if (filter.operator === \"between\") return value.length === 2 && value.every(Boolean);\n return value.length > 0 && value.every(Boolean);\n }\n return String(value).trim() !== \"\";\n}\n\n/** Human text for one value, resolving a `select` option to its label. */\nfunction valueLabel(field: FilterField | undefined, raw: string): string {\n const option = field?.options?.find((candidate) => candidate.value === raw);\n return option ? option.label : raw;\n}\n\n/**\n * One filter, in words: `\"Status é Pago\"`.\n *\n * Used for the chip and for the screen-reader announcement, from the same source —\n * a chip that reads `status=eq:paid` to a sighted user and something else to a\n * screen reader would be two different truths.\n */\nexport function describeFilter(\n filter: Filter,\n fields: readonly FilterField[],\n locale: \"pt-BR\" | \"en\" = \"pt-BR\",\n): string {\n const field = fields.find((candidate) => candidate.name === filter.field);\n const name = field?.label ?? filter.field;\n const operator = operatorLabel(filter.operator, locale);\n if (isValueless(filter.operator)) return `${name} ${operator}`;\n\n const values = Array.isArray(filter.value)\n ? filter.value.map((raw) => valueLabel(field, raw))\n : [valueLabel(field, String(filter.value ?? \"\"))];\n\n if (filter.operator === \"between\" && values.length === 2) {\n const joiner = locale === \"en\" ? \"and\" : \"e\";\n return `${name} ${operator} ${values[0]} ${joiner} ${values[1]}`;\n }\n return `${name} ${operator} ${values.join(\", \")}`;\n}\n\n/** Default operator for a field — the first one it offers. */\nexport function defaultOperator(field: FilterField): FilterOperator {\n return operatorsFor(field)[0] ?? \"eq\";\n}\n\n/**\n * Serialize filters into URL search params.\n *\n * One param per filter, `field=operator:value`, with `|` between the values of a\n * multi-value operator. A filter set that cannot survive a reload is a filter set\n * people re-enter every time they open a link somebody sent them, so this is part\n * of the model rather than something each app reinvents.\n *\n * Repeated fields are kept: `status=eq:paid&status=eq:sent` is two filters, and\n * collapsing them would silently drop one.\n *\n * @param filters - Applied filters.\n * @returns Params ready to merge into a location.\n */\nexport function filtersToSearchParams(filters: readonly Filter[]): URLSearchParams {\n const params = new URLSearchParams();\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n const value = Array.isArray(filter.value) ? filter.value.join(\"|\") : (filter.value ?? \"\");\n params.append(\n filter.field,\n isValueless(filter.operator) ? filter.operator : `${filter.operator}:${value}`,\n );\n }\n return params;\n}\n\n/**\n * Read filters back from URL search params.\n *\n * Anything that does not parse is dropped rather than guessed at: a hand-edited URL\n * is the normal way this input arrives, and rendering a filter the app cannot\n * evaluate would show a list that does not match what the chips claim.\n *\n * @param params - Params from the location.\n * @param fields - Known fields; a param naming anything else is ignored.\n * @returns The filters that parsed.\n */\nexport function filtersFromSearchParams(\n params: URLSearchParams,\n fields: readonly FilterField[],\n): Filter[] {\n const known = new Map(fields.map((field) => [field.name, field]));\n const filters: Filter[] = [];\n\n for (const [name, raw] of params.entries()) {\n const field = known.get(name);\n if (!field) continue;\n\n const separator = raw.indexOf(\":\");\n const operator = (separator < 0 ? raw : raw.slice(0, separator)) as FilterOperator;\n if (!operatorsFor(field).includes(operator)) continue;\n\n if (isValueless(operator)) {\n filters.push({ field: name, operator });\n continue;\n }\n if (separator < 0) continue;\n\n const rest = raw.slice(separator + 1);\n const value = isMulti(operator) ? rest.split(\"|\") : rest;\n const filter: Filter = { field: name, operator, value };\n if (isComplete(filter)) filters.push(filter);\n }\n\n return filters;\n}\n\n/** Labels the bar needs, per locale. */\ninterface FilterStrings {\n add: string;\n apply: string;\n cancel: string;\n clear: string;\n field: string;\n operator: string;\n value: string;\n from: string;\n to: string;\n yes: string;\n no: string;\n remove: (description: string) => string;\n active: (count: number) => string;\n empty: string;\n}\n\nconst PT_BR: FilterStrings = {\n add: \"Adicionar filtro\",\n apply: \"Aplicar\",\n cancel: \"Cancelar\",\n clear: \"Limpar filtros\",\n field: \"Campo\",\n operator: \"Condição\",\n value: \"Valor\",\n from: \"De\",\n to: \"Até\",\n yes: \"Sim\",\n no: \"Não\",\n remove: (description) => `Remover filtro: ${description}`,\n active: (count) => (count === 1 ? \"1 filtro ativo\" : `${count} filtros ativos`),\n empty: \"Nenhum filtro\",\n};\n\nconst EN: FilterStrings = {\n add: \"Add filter\",\n apply: \"Apply\",\n cancel: \"Cancel\",\n clear: \"Clear filters\",\n field: \"Field\",\n operator: \"Condition\",\n value: \"Value\",\n from: \"From\",\n to: \"To\",\n yes: \"Yes\",\n no: \"No\",\n remove: (description) => `Remove filter: ${description}`,\n active: (count) => (count === 1 ? \"1 active filter\" : `${count} active filters`),\n empty: \"No filters\",\n};\n\n/** Locale strings for the bar. */\nexport function filterStrings(locale: \"pt-BR\" | \"en\"): FilterStrings {\n return locale === \"en\" ? EN : PT_BR;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filter-model.cjs","names":["OPERATORS_BY_TYPE","VALUELESS","MULTI","OPERATOR_LABELS","operatorsFor","field","operatorLabel","locale","operator","isValueless","isMulti","isComplete","filter","value","valueLabel","option","candidate","raw","describeFilter","fields","name","values","joiner","defaultOperator","filtersToSearchParams","params","filters","filtersFromSearchParams","known","separator","rest","PT_BR","description","count","EN","filterStrings"],"sources":["../../../src/components/FilterBar/filter-model.ts"],"sourcesContent":["// The filter model behind `FilterBar`: what a field can be compared with, how a\n// filter reads in words, and how a filter set survives a page reload.\n//\n// Flat AND, deliberately. Nested `(a OR b) AND c` groups are a different component\n// with a different UI (a tree with per-node operators) and a different serialization\n// — trying to be both produces a builder that is clumsy for the 95% case, which is\n// \"status is paid, created after March, text contains nota\".\n\n/** Comparison a filter can make. */\nexport type FilterOperator =\n | \"eq\"\n | \"ne\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\"\n | \"in\"\n | \"empty\"\n | \"notEmpty\";\n\n/** Kind of value a field holds, which decides its operators and its input. */\nexport type FilterFieldType = \"text\" | \"number\" | \"date\" | \"select\" | \"boolean\";\n\n/** One filterable field. */\nexport interface FilterField {\n /** Key sent to the backend. */\n name: string;\n /** What the user sees. */\n label: string;\n type: FilterFieldType;\n /** Choices for `select`. */\n options?: ReadonlyArray<{ value: string; label: string }>;\n /** Restrict or reorder the operators offered. Defaults per type. */\n operators?: readonly FilterOperator[];\n /** Placeholder for the value input. */\n placeholder?: string;\n}\n\n/** One applied filter. */\nexport interface Filter {\n field: string;\n operator: FilterOperator;\n /** `between` carries a pair; `in` carries a list; `empty`/`notEmpty` carry nothing. */\n value?: string | readonly string[];\n}\n\n/** Operators offered per field type, in the order they appear. */\nconst OPERATORS_BY_TYPE: Record<FilterFieldType, FilterOperator[]> = {\n text: [\"contains\", \"eq\", \"ne\", \"empty\", \"notEmpty\"],\n number: [\"eq\", \"ne\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n date: [\"eq\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n select: [\"eq\", \"ne\", \"in\", \"empty\", \"notEmpty\"],\n boolean: [\"eq\"],\n};\n\n/** Operators that take no value at all. */\nconst VALUELESS: ReadonlySet<FilterOperator> = new Set([\"empty\", \"notEmpty\"]);\n\n/** Operators that take more than one value. */\nconst MULTI: ReadonlySet<FilterOperator> = new Set([\"between\", \"in\"]);\n\n/** Human labels for the operators, per locale. */\nconst OPERATOR_LABELS: Record<\"pt-BR\" | \"en\", Record<FilterOperator, string>> = {\n \"pt-BR\": {\n eq: \"é\",\n ne: \"não é\",\n contains: \"contém\",\n gt: \"maior que\",\n gte: \"maior ou igual a\",\n lt: \"menor que\",\n lte: \"menor ou igual a\",\n between: \"entre\",\n in: \"é um de\",\n empty: \"está vazio\",\n notEmpty: \"não está vazio\",\n },\n en: {\n eq: \"is\",\n ne: \"is not\",\n contains: \"contains\",\n gt: \"greater than\",\n gte: \"at least\",\n lt: \"less than\",\n lte: \"at most\",\n between: \"between\",\n in: \"is any of\",\n empty: \"is empty\",\n notEmpty: \"is not empty\",\n },\n};\n\n/** The operators a field offers. */\nexport function operatorsFor(field: FilterField): FilterOperator[] {\n return [...(field.operators ?? OPERATORS_BY_TYPE[field.type])];\n}\n\n/** Label of an operator. */\nexport function operatorLabel(operator: FilterOperator, locale: \"pt-BR\" | \"en\" = \"pt-BR\"): string {\n return OPERATOR_LABELS[locale][operator] ?? operator;\n}\n\n/** True when the operator needs no value input. */\nexport function isValueless(operator: FilterOperator): boolean {\n return VALUELESS.has(operator);\n}\n\n/** True when the operator takes several values. */\nexport function isMulti(operator: FilterOperator): boolean {\n return MULTI.has(operator);\n}\n\n/**\n * Is this filter complete enough to apply?\n *\n * An incomplete filter is not an error to shout about — it is a half-filled form.\n * The component uses this to keep \"Add\" disabled, which says the same thing without\n * a message nobody asked for.\n */\nexport function isComplete(filter: Filter): boolean {\n if (isValueless(filter.operator)) return true;\n const { value } = filter;\n if (value === undefined) return false;\n if (Array.isArray(value)) {\n if (filter.operator === \"between\") return value.length === 2 && value.every(Boolean);\n return value.length > 0 && value.every(Boolean);\n }\n return String(value).trim() !== \"\";\n}\n\n/** Human text for one value, resolving a `select` option to its label. */\nfunction valueLabel(field: FilterField | undefined, raw: string): string {\n const option = field?.options?.find((candidate) => candidate.value === raw);\n return option ? option.label : raw;\n}\n\n/**\n * One filter, in words: `\"Status é Pago\"`.\n *\n * Used for the chip and for the screen-reader announcement, from the same source —\n * a chip that reads `status=eq:paid` to a sighted user and something else to a\n * screen reader would be two different truths.\n */\nexport function describeFilter(\n filter: Filter,\n fields: readonly FilterField[],\n locale: \"pt-BR\" | \"en\" = \"pt-BR\",\n): string {\n const field = fields.find((candidate) => candidate.name === filter.field);\n const name = field?.label ?? filter.field;\n const operator = operatorLabel(filter.operator, locale);\n if (isValueless(filter.operator)) return `${name} ${operator}`;\n\n const values = Array.isArray(filter.value)\n ? filter.value.map((raw) => valueLabel(field, raw))\n : [valueLabel(field, String(filter.value ?? \"\"))];\n\n if (filter.operator === \"between\" && values.length === 2) {\n const joiner = locale === \"en\" ? \"and\" : \"e\";\n return `${name} ${operator} ${values[0]} ${joiner} ${values[1]}`;\n }\n return `${name} ${operator} ${values.join(\", \")}`;\n}\n\n/** Default operator for a field — the first one it offers. */\nexport function defaultOperator(field: FilterField): FilterOperator {\n return operatorsFor(field)[0] ?? \"eq\";\n}\n\n/**\n * Serialize filters into URL search params.\n *\n * One param per filter, `field=operator:value`, with `|` between the values of a\n * multi-value operator. A filter set that cannot survive a reload is a filter set\n * people re-enter every time they open a link somebody sent them, so this is part\n * of the model rather than something each app reinvents.\n *\n * Repeated fields are kept: `status=eq:paid&status=eq:sent` is two filters, and\n * collapsing them would silently drop one.\n *\n * @param filters - Applied filters.\n * @returns Params ready to merge into a location.\n */\nexport function filtersToSearchParams(filters: readonly Filter[]): URLSearchParams {\n const params = new URLSearchParams();\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n const value = Array.isArray(filter.value) ? filter.value.join(\"|\") : (filter.value ?? \"\");\n params.append(\n filter.field,\n isValueless(filter.operator) ? filter.operator : `${filter.operator}:${value}`,\n );\n }\n return params;\n}\n\n/**\n * Read filters back from URL search params.\n *\n * Anything that does not parse is dropped rather than guessed at: a hand-edited URL\n * is the normal way this input arrives, and rendering a filter the app cannot\n * evaluate would show a list that does not match what the chips claim.\n *\n * @param params - Params from the location.\n * @param fields - Known fields; a param naming anything else is ignored.\n * @returns The filters that parsed.\n */\nexport function filtersFromSearchParams(\n params: URLSearchParams,\n fields: readonly FilterField[],\n): Filter[] {\n const known = new Map(fields.map((field) => [field.name, field]));\n const filters: Filter[] = [];\n\n for (const [name, raw] of params.entries()) {\n const field = known.get(name);\n if (!field) continue;\n\n const separator = raw.indexOf(\":\");\n const operator = (separator < 0 ? raw : raw.slice(0, separator)) as FilterOperator;\n if (!operatorsFor(field).includes(operator)) continue;\n\n if (isValueless(operator)) {\n filters.push({ field: name, operator });\n continue;\n }\n if (separator < 0) continue;\n\n const rest = raw.slice(separator + 1);\n const value = isMulti(operator) ? rest.split(\"|\") : rest;\n const filter: Filter = { field: name, operator, value };\n if (isComplete(filter)) filters.push(filter);\n }\n\n return filters;\n}\n\n/** Labels the bar needs, per locale. */\ninterface FilterStrings {\n add: string;\n apply: string;\n cancel: string;\n clear: string;\n field: string;\n operator: string;\n value: string;\n from: string;\n to: string;\n yes: string;\n no: string;\n remove: (description: string) => string;\n active: (count: number) => string;\n empty: string;\n}\n\nconst PT_BR: FilterStrings = {\n add: \"Adicionar filtro\",\n apply: \"Aplicar\",\n cancel: \"Cancelar\",\n clear: \"Limpar filtros\",\n field: \"Campo\",\n operator: \"Condição\",\n value: \"Valor\",\n from: \"De\",\n to: \"Até\",\n yes: \"Sim\",\n no: \"Não\",\n remove: (description) => `Remover filtro: ${description}`,\n active: (count) => (count === 1 ? \"1 filtro ativo\" : `${count} filtros ativos`),\n empty: \"Nenhum filtro\",\n};\n\nconst EN: FilterStrings = {\n add: \"Add filter\",\n apply: \"Apply\",\n cancel: \"Cancel\",\n clear: \"Clear filters\",\n field: \"Field\",\n operator: \"Condition\",\n value: \"Value\",\n from: \"From\",\n to: \"To\",\n yes: \"Yes\",\n no: \"No\",\n remove: (description) => `Remove filter: ${description}`,\n active: (count) => (count === 1 ? \"1 active filter\" : `${count} active filters`),\n empty: \"No filters\",\n};\n\n/** Locale strings for the bar. */\nexport function filterStrings(locale: \"pt-BR\" | \"en\"): FilterStrings {\n return locale === \"en\" ? EN : PT_BR;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter-model.js","names":[],"sources":["../../../src/components/FilterBar/filter-model.ts"],"sourcesContent":["// The filter model behind `FilterBar`: what a field can be compared with, how a\n// filter reads in words, and how a filter set survives a page reload.\n//\n// Flat AND, deliberately. Nested `(a OR b) AND c` groups are a different component\n// with a different UI (a tree with per-node operators) and a different serialization\n// — trying to be both produces a builder that is clumsy for the 95% case, which is\n// \"status is paid, created after March, text contains nota\".\n\n/** Comparison a filter can make. */\nexport type FilterOperator =\n | \"eq\"\n | \"ne\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\"\n | \"in\"\n | \"empty\"\n | \"notEmpty\";\n\n/** Kind of value a field holds, which decides its operators and its input. */\nexport type FilterFieldType = \"text\" | \"number\" | \"date\" | \"select\" | \"boolean\";\n\n/** One filterable field. */\nexport interface FilterField {\n /** Key sent to the backend. */\n name: string;\n /** What the user sees. */\n label: string;\n type: FilterFieldType;\n /** Choices for `select`. */\n options?: ReadonlyArray<{ value: string; label: string }>;\n /** Restrict or reorder the operators offered. Defaults per type. */\n operators?: readonly FilterOperator[];\n /** Placeholder for the value input. */\n placeholder?: string;\n}\n\n/** One applied filter. */\nexport interface Filter {\n field: string;\n operator: FilterOperator;\n /** `between` carries a pair; `in` carries a list; `empty`/`notEmpty` carry nothing. */\n value?: string | readonly string[];\n}\n\n/** Operators offered per field type, in the order they appear. */\nconst OPERATORS_BY_TYPE: Record<FilterFieldType, FilterOperator[]> = {\n text: [\"contains\", \"eq\", \"ne\", \"empty\", \"notEmpty\"],\n number: [\"eq\", \"ne\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n date: [\"eq\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n select: [\"eq\", \"ne\", \"in\", \"empty\", \"notEmpty\"],\n boolean: [\"eq\"],\n};\n\n/** Operators that take no value at all. */\nconst VALUELESS: ReadonlySet<FilterOperator> = new Set([\"empty\", \"notEmpty\"]);\n\n/** Operators that take more than one value. */\nconst MULTI: ReadonlySet<FilterOperator> = new Set([\"between\", \"in\"]);\n\n/** Human labels for the operators, per locale. */\nconst OPERATOR_LABELS: Record<\"pt-BR\" | \"en\", Record<FilterOperator, string>> = {\n \"pt-BR\": {\n eq: \"é\",\n ne: \"não é\",\n contains: \"contém\",\n gt: \"maior que\",\n gte: \"maior ou igual a\",\n lt: \"menor que\",\n lte: \"menor ou igual a\",\n between: \"entre\",\n in: \"é um de\",\n empty: \"está vazio\",\n notEmpty: \"não está vazio\",\n },\n en: {\n eq: \"is\",\n ne: \"is not\",\n contains: \"contains\",\n gt: \"greater than\",\n gte: \"at least\",\n lt: \"less than\",\n lte: \"at most\",\n between: \"between\",\n in: \"is any of\",\n empty: \"is empty\",\n notEmpty: \"is not empty\",\n },\n};\n\n/** The operators a field offers. */\nexport function operatorsFor(field: FilterField): FilterOperator[] {\n return [...(field.operators ?? OPERATORS_BY_TYPE[field.type])];\n}\n\n/** Label of an operator. */\nexport function operatorLabel(operator: FilterOperator, locale: \"pt-BR\" | \"en\" = \"pt-BR\"): string {\n return OPERATOR_LABELS[locale][operator] ?? operator;\n}\n\n/** True when the operator needs no value input. */\nexport function isValueless(operator: FilterOperator): boolean {\n return VALUELESS.has(operator);\n}\n\n/** True when the operator takes several values. */\nexport function isMulti(operator: FilterOperator): boolean {\n return MULTI.has(operator);\n}\n\n/**\n * Is this filter complete enough to apply?\n *\n * An incomplete filter is not an error to shout about — it is a half-filled form.\n * The component uses this to keep \"Add\" disabled, which says the same thing without\n * a message nobody asked for.\n */\nexport function isComplete(filter: Filter): boolean {\n if (isValueless(filter.operator)) return true;\n const { value } = filter;\n if (value === undefined) return false;\n if (Array.isArray(value)) {\n if (filter.operator === \"between\") return value.length === 2 && value.every(Boolean);\n return value.length > 0 && value.every(Boolean);\n }\n return String(value).trim() !== \"\";\n}\n\n/** Human text for one value, resolving a `select` option to its label. */\nfunction valueLabel(field: FilterField | undefined, raw: string): string {\n const option = field?.options?.find((candidate) => candidate.value === raw);\n return option ? option.label : raw;\n}\n\n/**\n * One filter, in words: `\"Status é Pago\"`.\n *\n * Used for the chip and for the screen-reader announcement, from the same source —\n * a chip that reads `status=eq:paid` to a sighted user and something else to a\n * screen reader would be two different truths.\n */\nexport function describeFilter(\n filter: Filter,\n fields: readonly FilterField[],\n locale: \"pt-BR\" | \"en\" = \"pt-BR\",\n): string {\n const field = fields.find((candidate) => candidate.name === filter.field);\n const name = field?.label ?? filter.field;\n const operator = operatorLabel(filter.operator, locale);\n if (isValueless(filter.operator)) return `${name} ${operator}`;\n\n const values = Array.isArray(filter.value)\n ? filter.value.map((raw) => valueLabel(field, raw))\n : [valueLabel(field, String(filter.value ?? \"\"))];\n\n if (filter.operator === \"between\" && values.length === 2) {\n const joiner = locale === \"en\" ? \"and\" : \"e\";\n return `${name} ${operator} ${values[0]} ${joiner} ${values[1]}`;\n }\n return `${name} ${operator} ${values.join(\", \")}`;\n}\n\n/** Default operator for a field — the first one it offers. */\nexport function defaultOperator(field: FilterField): FilterOperator {\n return operatorsFor(field)[0] ?? \"eq\";\n}\n\n/**\n * Serialize filters into URL search params.\n *\n * One param per filter, `field=operator:value`, with `|` between the values of a\n * multi-value operator. A filter set that cannot survive a reload is a filter set\n * people re-enter every time they open a link somebody sent them, so this is part\n * of the model rather than something each app reinvents.\n *\n * Repeated fields are kept: `status=eq:paid&status=eq:sent` is two filters, and\n * collapsing them would silently drop one.\n *\n * @param filters - Applied filters.\n * @returns Params ready to merge into a location.\n */\nexport function filtersToSearchParams(filters: readonly Filter[]): URLSearchParams {\n const params = new URLSearchParams();\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n const value = Array.isArray(filter.value) ? filter.value.join(\"|\") : (filter.value ?? \"\");\n params.append(\n filter.field,\n isValueless(filter.operator) ? filter.operator : `${filter.operator}:${value}`,\n );\n }\n return params;\n}\n\n/**\n * Read filters back from URL search params.\n *\n * Anything that does not parse is dropped rather than guessed at: a hand-edited URL\n * is the normal way this input arrives, and rendering a filter the app cannot\n * evaluate would show a list that does not match what the chips claim.\n *\n * @param params - Params from the location.\n * @param fields - Known fields; a param naming anything else is ignored.\n * @returns The filters that parsed.\n */\nexport function filtersFromSearchParams(\n params: URLSearchParams,\n fields: readonly FilterField[],\n): Filter[] {\n const known = new Map(fields.map((field) => [field.name, field]));\n const filters: Filter[] = [];\n\n for (const [name, raw] of params.entries()) {\n const field = known.get(name);\n if (!field) continue;\n\n const separator = raw.indexOf(\":\");\n const operator = (separator < 0 ? raw : raw.slice(0, separator)) as FilterOperator;\n if (!operatorsFor(field).includes(operator)) continue;\n\n if (isValueless(operator)) {\n filters.push({ field: name, operator });\n continue;\n }\n if (separator < 0) continue;\n\n const rest = raw.slice(separator + 1);\n const value = isMulti(operator) ? rest.split(\"|\") : rest;\n const filter: Filter = { field: name, operator, value };\n if (isComplete(filter)) filters.push(filter);\n }\n\n return filters;\n}\n\n/** Labels the bar needs, per locale. */\ninterface FilterStrings {\n add: string;\n apply: string;\n cancel: string;\n clear: string;\n field: string;\n operator: string;\n value: string;\n from: string;\n to: string;\n yes: string;\n no: string;\n remove: (description: string) => string;\n active: (count: number) => string;\n empty: string;\n}\n\nconst PT_BR: FilterStrings = {\n add: \"Adicionar filtro\",\n apply: \"Aplicar\",\n cancel: \"Cancelar\",\n clear: \"Limpar filtros\",\n field: \"Campo\",\n operator: \"Condição\",\n value: \"Valor\",\n from: \"De\",\n to: \"Até\",\n yes: \"Sim\",\n no: \"Não\",\n remove: (description) => `Remover filtro: ${description}`,\n active: (count) => (count === 1 ? \"1 filtro ativo\" : `${count} filtros ativos`),\n empty: \"Nenhum filtro\",\n};\n\nconst EN: FilterStrings = {\n add: \"Add filter\",\n apply: \"Apply\",\n cancel: \"Cancel\",\n clear: \"Clear filters\",\n field: \"Field\",\n operator: \"Condition\",\n value: \"Value\",\n from: \"From\",\n to: \"To\",\n yes: \"Yes\",\n no: \"No\",\n remove: (description) => `Remove filter: ${description}`,\n active: (count) => (count === 1 ? \"1 active filter\" : `${count} active filters`),\n empty: \"No filters\",\n};\n\n/** Locale strings for the bar. */\nexport function filterStrings(locale: \"pt-BR\" | \"en\"): FilterStrings {\n return locale === \"en\" ? EN : PT_BR;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filter-model.js","names":["OPERATORS_BY_TYPE","VALUELESS","MULTI","OPERATOR_LABELS","operatorsFor","field","operatorLabel","locale","operator","isValueless","isMulti","isComplete","filter","value","valueLabel","option","candidate","raw","describeFilter","fields","name","values","joiner","defaultOperator","filtersToSearchParams","params","filters","filtersFromSearchParams","known","separator","rest","PT_BR","description","count","EN","filterStrings"],"sources":["../../../src/components/FilterBar/filter-model.ts"],"sourcesContent":["// The filter model behind `FilterBar`: what a field can be compared with, how a\n// filter reads in words, and how a filter set survives a page reload.\n//\n// Flat AND, deliberately. Nested `(a OR b) AND c` groups are a different component\n// with a different UI (a tree with per-node operators) and a different serialization\n// — trying to be both produces a builder that is clumsy for the 95% case, which is\n// \"status is paid, created after March, text contains nota\".\n\n/** Comparison a filter can make. */\nexport type FilterOperator =\n | \"eq\"\n | \"ne\"\n | \"contains\"\n | \"gt\"\n | \"gte\"\n | \"lt\"\n | \"lte\"\n | \"between\"\n | \"in\"\n | \"empty\"\n | \"notEmpty\";\n\n/** Kind of value a field holds, which decides its operators and its input. */\nexport type FilterFieldType = \"text\" | \"number\" | \"date\" | \"select\" | \"boolean\";\n\n/** One filterable field. */\nexport interface FilterField {\n /** Key sent to the backend. */\n name: string;\n /** What the user sees. */\n label: string;\n type: FilterFieldType;\n /** Choices for `select`. */\n options?: ReadonlyArray<{ value: string; label: string }>;\n /** Restrict or reorder the operators offered. Defaults per type. */\n operators?: readonly FilterOperator[];\n /** Placeholder for the value input. */\n placeholder?: string;\n}\n\n/** One applied filter. */\nexport interface Filter {\n field: string;\n operator: FilterOperator;\n /** `between` carries a pair; `in` carries a list; `empty`/`notEmpty` carry nothing. */\n value?: string | readonly string[];\n}\n\n/** Operators offered per field type, in the order they appear. */\nconst OPERATORS_BY_TYPE: Record<FilterFieldType, FilterOperator[]> = {\n text: [\"contains\", \"eq\", \"ne\", \"empty\", \"notEmpty\"],\n number: [\"eq\", \"ne\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n date: [\"eq\", \"gt\", \"gte\", \"lt\", \"lte\", \"between\"],\n select: [\"eq\", \"ne\", \"in\", \"empty\", \"notEmpty\"],\n boolean: [\"eq\"],\n};\n\n/** Operators that take no value at all. */\nconst VALUELESS: ReadonlySet<FilterOperator> = new Set([\"empty\", \"notEmpty\"]);\n\n/** Operators that take more than one value. */\nconst MULTI: ReadonlySet<FilterOperator> = new Set([\"between\", \"in\"]);\n\n/** Human labels for the operators, per locale. */\nconst OPERATOR_LABELS: Record<\"pt-BR\" | \"en\", Record<FilterOperator, string>> = {\n \"pt-BR\": {\n eq: \"é\",\n ne: \"não é\",\n contains: \"contém\",\n gt: \"maior que\",\n gte: \"maior ou igual a\",\n lt: \"menor que\",\n lte: \"menor ou igual a\",\n between: \"entre\",\n in: \"é um de\",\n empty: \"está vazio\",\n notEmpty: \"não está vazio\",\n },\n en: {\n eq: \"is\",\n ne: \"is not\",\n contains: \"contains\",\n gt: \"greater than\",\n gte: \"at least\",\n lt: \"less than\",\n lte: \"at most\",\n between: \"between\",\n in: \"is any of\",\n empty: \"is empty\",\n notEmpty: \"is not empty\",\n },\n};\n\n/** The operators a field offers. */\nexport function operatorsFor(field: FilterField): FilterOperator[] {\n return [...(field.operators ?? OPERATORS_BY_TYPE[field.type])];\n}\n\n/** Label of an operator. */\nexport function operatorLabel(operator: FilterOperator, locale: \"pt-BR\" | \"en\" = \"pt-BR\"): string {\n return OPERATOR_LABELS[locale][operator] ?? operator;\n}\n\n/** True when the operator needs no value input. */\nexport function isValueless(operator: FilterOperator): boolean {\n return VALUELESS.has(operator);\n}\n\n/** True when the operator takes several values. */\nexport function isMulti(operator: FilterOperator): boolean {\n return MULTI.has(operator);\n}\n\n/**\n * Is this filter complete enough to apply?\n *\n * An incomplete filter is not an error to shout about — it is a half-filled form.\n * The component uses this to keep \"Add\" disabled, which says the same thing without\n * a message nobody asked for.\n */\nexport function isComplete(filter: Filter): boolean {\n if (isValueless(filter.operator)) return true;\n const { value } = filter;\n if (value === undefined) return false;\n if (Array.isArray(value)) {\n if (filter.operator === \"between\") return value.length === 2 && value.every(Boolean);\n return value.length > 0 && value.every(Boolean);\n }\n return String(value).trim() !== \"\";\n}\n\n/** Human text for one value, resolving a `select` option to its label. */\nfunction valueLabel(field: FilterField | undefined, raw: string): string {\n const option = field?.options?.find((candidate) => candidate.value === raw);\n return option ? option.label : raw;\n}\n\n/**\n * One filter, in words: `\"Status é Pago\"`.\n *\n * Used for the chip and for the screen-reader announcement, from the same source —\n * a chip that reads `status=eq:paid` to a sighted user and something else to a\n * screen reader would be two different truths.\n */\nexport function describeFilter(\n filter: Filter,\n fields: readonly FilterField[],\n locale: \"pt-BR\" | \"en\" = \"pt-BR\",\n): string {\n const field = fields.find((candidate) => candidate.name === filter.field);\n const name = field?.label ?? filter.field;\n const operator = operatorLabel(filter.operator, locale);\n if (isValueless(filter.operator)) return `${name} ${operator}`;\n\n const values = Array.isArray(filter.value)\n ? filter.value.map((raw) => valueLabel(field, raw))\n : [valueLabel(field, String(filter.value ?? \"\"))];\n\n if (filter.operator === \"between\" && values.length === 2) {\n const joiner = locale === \"en\" ? \"and\" : \"e\";\n return `${name} ${operator} ${values[0]} ${joiner} ${values[1]}`;\n }\n return `${name} ${operator} ${values.join(\", \")}`;\n}\n\n/** Default operator for a field — the first one it offers. */\nexport function defaultOperator(field: FilterField): FilterOperator {\n return operatorsFor(field)[0] ?? \"eq\";\n}\n\n/**\n * Serialize filters into URL search params.\n *\n * One param per filter, `field=operator:value`, with `|` between the values of a\n * multi-value operator. A filter set that cannot survive a reload is a filter set\n * people re-enter every time they open a link somebody sent them, so this is part\n * of the model rather than something each app reinvents.\n *\n * Repeated fields are kept: `status=eq:paid&status=eq:sent` is two filters, and\n * collapsing them would silently drop one.\n *\n * @param filters - Applied filters.\n * @returns Params ready to merge into a location.\n */\nexport function filtersToSearchParams(filters: readonly Filter[]): URLSearchParams {\n const params = new URLSearchParams();\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n const value = Array.isArray(filter.value) ? filter.value.join(\"|\") : (filter.value ?? \"\");\n params.append(\n filter.field,\n isValueless(filter.operator) ? filter.operator : `${filter.operator}:${value}`,\n );\n }\n return params;\n}\n\n/**\n * Read filters back from URL search params.\n *\n * Anything that does not parse is dropped rather than guessed at: a hand-edited URL\n * is the normal way this input arrives, and rendering a filter the app cannot\n * evaluate would show a list that does not match what the chips claim.\n *\n * @param params - Params from the location.\n * @param fields - Known fields; a param naming anything else is ignored.\n * @returns The filters that parsed.\n */\nexport function filtersFromSearchParams(\n params: URLSearchParams,\n fields: readonly FilterField[],\n): Filter[] {\n const known = new Map(fields.map((field) => [field.name, field]));\n const filters: Filter[] = [];\n\n for (const [name, raw] of params.entries()) {\n const field = known.get(name);\n if (!field) continue;\n\n const separator = raw.indexOf(\":\");\n const operator = (separator < 0 ? raw : raw.slice(0, separator)) as FilterOperator;\n if (!operatorsFor(field).includes(operator)) continue;\n\n if (isValueless(operator)) {\n filters.push({ field: name, operator });\n continue;\n }\n if (separator < 0) continue;\n\n const rest = raw.slice(separator + 1);\n const value = isMulti(operator) ? rest.split(\"|\") : rest;\n const filter: Filter = { field: name, operator, value };\n if (isComplete(filter)) filters.push(filter);\n }\n\n return filters;\n}\n\n/** Labels the bar needs, per locale. */\ninterface FilterStrings {\n add: string;\n apply: string;\n cancel: string;\n clear: string;\n field: string;\n operator: string;\n value: string;\n from: string;\n to: string;\n yes: string;\n no: string;\n remove: (description: string) => string;\n active: (count: number) => string;\n empty: string;\n}\n\nconst PT_BR: FilterStrings = {\n add: \"Adicionar filtro\",\n apply: \"Aplicar\",\n cancel: \"Cancelar\",\n clear: \"Limpar filtros\",\n field: \"Campo\",\n operator: \"Condição\",\n value: \"Valor\",\n from: \"De\",\n to: \"Até\",\n yes: \"Sim\",\n no: \"Não\",\n remove: (description) => `Remover filtro: ${description}`,\n active: (count) => (count === 1 ? \"1 filtro ativo\" : `${count} filtros ativos`),\n empty: \"Nenhum filtro\",\n};\n\nconst EN: FilterStrings = {\n add: \"Add filter\",\n apply: \"Apply\",\n cancel: \"Cancel\",\n clear: \"Clear filters\",\n field: \"Field\",\n operator: \"Condition\",\n value: \"Value\",\n from: \"From\",\n to: \"To\",\n yes: \"Yes\",\n no: \"No\",\n remove: (description) => `Remove filter: ${description}`,\n active: (count) => (count === 1 ? \"1 active filter\" : `${count} active filters`),\n empty: \"No filters\",\n};\n\n/** Locale strings for the bar. */\nexport function filterStrings(locale: \"pt-BR\" | \"en\"): FilterStrings {\n return locale === \"en\" ? EN : PT_BR;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("./filter-model.cjs"),t=require("./filter-apply.cjs");var n={eq:``,ne:`__ne`,contains:`__icontains`,gt:`__gt`,gte:`__gte`,lt:`__lt`,lte:`__lte`,between:`__between`,in:`__in`,empty:`__isnull`,notEmpty:`__isnull`},r=new Set([`name`]);function i(i,a={}){let o=a.operatorSuffix?{...n,...a.operatorSuffix}:n,s=a.substringColumns?new Set(a.substringColumns):r,c=new URLSearchParams;for(let n of i){if(!e.isComplete(n))continue;let r=o[n.operator],i=n.operator===`eq`&&s.has(n.field)?`${n.field}__iexact`:`${n.field}${r}`;if(n.operator===`empty`||n.operator===`notEmpty`){c.append(i,n.operator===`empty`?`true`:`false`);continue}let a=Array.isArray(n.value)?[...n.value]:[String(n.value??``)];if(n.operator===`between`){for(let e of t.orderRange(a))c.append(i,e);continue}for(let e of a)c.append(i,e)}return c}exports.filtersToQueryParams=i;
1
+ const e=require("./filter-model.cjs"),t=require("./filter-apply.cjs");var n={eq:``,ne:`__ne`,contains:`__icontains`,gt:`__gt`,gte:`__gte`,lt:`__lt`,lte:`__lte`,between:`__between`,in:`__in`,empty:`__isnull`,notEmpty:`__isnull`},r=new Set([`name`]);function i(i,a={}){let o=a.operatorSuffix?{...n,...a.operatorSuffix}:n,s=a.substringColumns?new Set(a.substringColumns):r,c=new URLSearchParams;for(let n of i){if(!e.isComplete(n))continue;let r=o[n.operator],i=n.operator===`eq`&&s.has(n.field)?`${n.field}__iexact`:`${n.field}${r}`;if(n.operator===`empty`||n.operator===`notEmpty`){c.append(i,n.operator===`empty`?`true`:`false`);continue}let a=Array.isArray(n.value)?[...n.value]:[String(n.value??``)];if(n.operator===`between`)for(let e of t.orderRange(a))c.append(i,e);else for(let e of a)c.append(i,e)}return c}exports.filtersToQueryParams=i;
2
2
  //# sourceMappingURL=filter-query.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-query.cjs","names":[],"sources":["../../../src/components/FilterBar/filter-query.ts"],"sourcesContent":["// Server-side half of the filter model: the same `Filter[]` the bar produces,\n// encoded the way a paginated backend expects to read it. Kept apart from\n// `filtersToSearchParams` (filter-model.ts) because the two answer different\n// questions — that one round-trips the UI state through the URL, this one talks\n// to an API and its shape is the API's, not ours.\n\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\nimport { orderRange } from \"./filter-apply\";\n\n/**\n * Operator suffix per filter operator, following the `<column>__<op>` convention\n * of `tempest-fastapi-sdk`.\n *\n * Ported from `build_filter_condition` in\n * `tempest_fastapi_sdk/db/expressions.py`, which is what `BaseRepository`\n * dict filters and `Q` both resolve through. An empty suffix means the bare\n * column name, which that function resolves to plain equality.\n *\n * `contains` maps to `icontains` (case-insensitive, and the backend escapes the\n * `LIKE` wildcards) and both emptiness operators map to `isnull`, whose value\n * carries the direction.\n */\nconst DEFAULT_OPERATOR_SUFFIX: Record<FilterOperator, string> = {\n eq: \"\",\n ne: \"__ne\",\n contains: \"__icontains\",\n gt: \"__gt\",\n gte: \"__gte\",\n lt: \"__lt\",\n lte: \"__lte\",\n between: \"__between\",\n in: \"__in\",\n empty: \"__isnull\",\n notEmpty: \"__isnull\",\n};\n\n/**\n * Columns the backend treats as a substring search when they carry no operator\n * suffix.\n *\n * Ported from `build_filter_condition`, which special-cases a string `name` into\n * `ILIKE %value%`. Sending a bare `name=` for an `eq` filter would therefore ask\n * for \"contains\" while the chip says \"is\", so `eq` on such a column is emitted as\n * `name__iexact` instead.\n */\nconst DEFAULT_SUBSTRING_COLUMNS: ReadonlySet<string> = new Set([\"name\"]);\n\n/** Overrides for the backend dialect {@link filtersToQueryParams} encodes into. */\nexport interface FiltersToQueryParamsOptions {\n /**\n * Columns whose `eq` is emitted as `<column>__iexact` rather than as the bare\n * column name. Default `[\"name\"]`, which is what `build_filter_condition`\n * special-cases.\n *\n * Pass the columns **your** backend treats that way — `nome`, `titulo`,\n * `razao_social` — or `[]` when it treats none of them specially and a bare\n * `eq` should stay bare.\n */\n substringColumns?: readonly string[];\n /**\n * Operator suffixes, merged over the `tempest-fastapi-sdk` dialect, so an\n * override names only the operators that differ.\n *\n * @example\n * // A DRF-style backend\n * filtersToQueryParams(filters, {\n * substringColumns: [],\n * operatorSuffix: { contains: \"__icontains\", ne: \"__exclude\" },\n * });\n */\n operatorSuffix?: Partial<Record<FilterOperator, string>>;\n}\n\n/**\n * Encode filters as query params for a paginated backend.\n *\n * The counterpart of {@link applyFilters}: same filter set, evaluated by the\n * database instead of by the browser, which is the only option once the list is\n * paginated on the server and the page in memory is not the whole result.\n *\n * The encoding is the `<column>__<op>` convention `tempest-fastapi-sdk` already\n * reads (`BaseRepository._apply_filters` → `build_filter_condition`):\n *\n * | Operator | Param |\n * | --- | --- |\n * | `eq` | `field` (or `field__iexact` for the `name` column) |\n * | `ne` | `field__ne` |\n * | `contains` | `field__icontains` |\n * | `gt` `gte` `lt` `lte` | `field__gt` … `field__lte` |\n * | `between` | `field__between` twice, low value first |\n * | `in` | `field__in` once per value |\n * | `empty` / `notEmpty` | `field__isnull=true` / `=false` |\n *\n * Returns `URLSearchParams` rather than a plain object because `between` carries\n * a pair and `in` carries a list: an object would keep only the last value of\n * each, silently narrowing the filter. Repeated params are also how FastAPI\n * receives a `list[str]` declared with `Query`.\n *\n * Two things the backend has to hold up its end of, or the filter fails quietly:\n *\n * - **Every key must be declared.** `BasePaginationFilterSchema.get_conditions()`\n * only forwards fields the subclass declares, so a `status__ne` the schema\n * never mentions is dropped by FastAPI before the repository sees it — no\n * error, no filtering.\n * - **`isnull` matches `NULL` only.** A column that stores `\"\"` for \"no value\"\n * will not answer an `empty` filter, while {@link applyFilters} treats blank\n * text as empty.\n *\n * The defaults are that dialect, not a universal truth. A backend that names its\n * substring column something other than `name`, or that spells its operators\n * differently, passes `options` — the alternative was an encoder whose special\n * cases were a wall for anyone not on the Tempest stack.\n *\n * @example\n * const params = filtersToQueryParams(filters);\n * params.set(\"page\", String(page));\n * const data = await api.get(`/orders?${params}`);\n *\n * @example\n * // A backend whose searchable column is `razao_social` and that spells `ne`\n * // the Django way.\n * const params = filtersToQueryParams(filters, {\n * substringColumns: [\"razao_social\"],\n * operatorSuffix: { ne: \"__exclude\" },\n * });\n *\n * @param filters - Applied filters; incomplete ones are ignored.\n * @param options - Dialect overrides. Defaults to the `tempest-fastapi-sdk` one.\n * @returns Params ready to append to a request URL.\n */\nexport function filtersToQueryParams(\n filters: readonly Filter[],\n options: FiltersToQueryParamsOptions = {},\n): URLSearchParams {\n const suffixes = options.operatorSuffix\n ? { ...DEFAULT_OPERATOR_SUFFIX, ...options.operatorSuffix }\n : DEFAULT_OPERATOR_SUFFIX;\n const substringColumns = options.substringColumns\n ? new Set(options.substringColumns)\n : DEFAULT_SUBSTRING_COLUMNS;\n\n const params = new URLSearchParams();\n\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n\n const suffix = suffixes[filter.operator];\n const key =\n filter.operator === \"eq\" && substringColumns.has(filter.field)\n ? `${filter.field}__iexact`\n : `${filter.field}${suffix}`;\n\n if (filter.operator === \"empty\" || filter.operator === \"notEmpty\") {\n params.append(key, filter.operator === \"empty\" ? \"true\" : \"false\");\n continue;\n }\n\n const values = Array.isArray(filter.value)\n ? [...filter.value]\n : [String(filter.value ?? \"\")];\n\n if (filter.operator === \"between\") {\n for (const value of orderRange(values)) params.append(key, value);\n continue;\n }\n\n for (const value of values) params.append(key, value);\n }\n\n return params;\n}\n"],"mappings":"sEAuBA,IAAM,EAA0D,CAC5D,GAAI,GACJ,GAAI,OACJ,SAAU,cACV,GAAI,OACJ,IAAK,QACL,GAAI,OACJ,IAAK,QACL,QAAS,YACT,GAAI,OACJ,MAAO,WACP,SAAU,UACd,EAWM,EAAiD,IAAI,IAAI,CAAC,MAAM,CAAC,EAqFvE,SAAgB,EACZ,EACA,EAAuC,CAAC,EACzB,CACf,IAAM,EAAW,EAAQ,eACnB,CAAE,GAAG,EAAyB,GAAG,EAAQ,cAAe,EACxD,EACA,EAAmB,EAAQ,iBAC3B,IAAI,IAAI,EAAQ,gBAAgB,EAChC,EAEA,EAAS,IAAI,gBAEnB,IAAK,IAAM,KAAU,EAAS,CAC1B,GAAI,CAAC,EAAA,WAAW,CAAM,EAAG,SAEzB,IAAM,EAAS,EAAS,EAAO,UACzB,EACF,EAAO,WAAa,MAAQ,EAAiB,IAAI,EAAO,KAAK,EACvD,GAAG,EAAO,MAAM,UAChB,GAAG,EAAO,QAAQ,IAE5B,GAAI,EAAO,WAAa,SAAW,EAAO,WAAa,WAAY,CAC/D,EAAO,OAAO,EAAK,EAAO,WAAa,QAAU,OAAS,OAAO,EACjE,QACJ,CAEA,IAAM,EAAS,MAAM,QAAQ,EAAO,KAAK,EACnC,CAAC,GAAG,EAAO,KAAK,EAChB,CAAC,OAAO,EAAO,OAAS,EAAE,CAAC,EAEjC,GAAI,EAAO,WAAa,UAAW,CAC/B,IAAK,IAAM,KAAS,EAAA,WAAW,CAAM,EAAG,EAAO,OAAO,EAAK,CAAK,EAChE,QACJ,CAEA,IAAK,IAAM,KAAS,EAAQ,EAAO,OAAO,EAAK,CAAK,CACxD,CAEA,OAAO,CACX"}
1
+ {"version":3,"file":"filter-query.cjs","names":["isComplete","orderRange","require_filter_model","require_filter_apply","DEFAULT_OPERATOR_SUFFIX","DEFAULT_SUBSTRING_COLUMNS","filtersToQueryParams","suffixes","options","substringColumns","params","filter","filters","suffix","key","values","value"],"sources":["../../../src/components/FilterBar/filter-query.ts"],"sourcesContent":["// Server-side half of the filter model: the same `Filter[]` the bar produces,\n// encoded the way a paginated backend expects to read it. Kept apart from\n// `filtersToSearchParams` (filter-model.ts) because the two answer different\n// questions — that one round-trips the UI state through the URL, this one talks\n// to an API and its shape is the API's, not ours.\n\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\nimport { orderRange } from \"./filter-apply\";\n\n/**\n * Operator suffix per filter operator, following the `<column>__<op>` convention\n * of `tempest-fastapi-sdk`.\n *\n * Ported from `build_filter_condition` in\n * `tempest_fastapi_sdk/db/expressions.py`, which is what `BaseRepository`\n * dict filters and `Q` both resolve through. An empty suffix means the bare\n * column name, which that function resolves to plain equality.\n *\n * `contains` maps to `icontains` (case-insensitive, and the backend escapes the\n * `LIKE` wildcards) and both emptiness operators map to `isnull`, whose value\n * carries the direction.\n */\nconst DEFAULT_OPERATOR_SUFFIX: Record<FilterOperator, string> = {\n eq: \"\",\n ne: \"__ne\",\n contains: \"__icontains\",\n gt: \"__gt\",\n gte: \"__gte\",\n lt: \"__lt\",\n lte: \"__lte\",\n between: \"__between\",\n in: \"__in\",\n empty: \"__isnull\",\n notEmpty: \"__isnull\",\n};\n\n/**\n * Columns the backend treats as a substring search when they carry no operator\n * suffix.\n *\n * Ported from `build_filter_condition`, which special-cases a string `name` into\n * `ILIKE %value%`. Sending a bare `name=` for an `eq` filter would therefore ask\n * for \"contains\" while the chip says \"is\", so `eq` on such a column is emitted as\n * `name__iexact` instead.\n */\nconst DEFAULT_SUBSTRING_COLUMNS: ReadonlySet<string> = new Set([\"name\"]);\n\n/** Overrides for the backend dialect {@link filtersToQueryParams} encodes into. */\nexport interface FiltersToQueryParamsOptions {\n /**\n * Columns whose `eq` is emitted as `<column>__iexact` rather than as the bare\n * column name. Default `[\"name\"]`, which is what `build_filter_condition`\n * special-cases.\n *\n * Pass the columns **your** backend treats that way — `nome`, `titulo`,\n * `razao_social` — or `[]` when it treats none of them specially and a bare\n * `eq` should stay bare.\n */\n substringColumns?: readonly string[];\n /**\n * Operator suffixes, merged over the `tempest-fastapi-sdk` dialect, so an\n * override names only the operators that differ.\n *\n * @example\n * // A DRF-style backend\n * filtersToQueryParams(filters, {\n * substringColumns: [],\n * operatorSuffix: { contains: \"__icontains\", ne: \"__exclude\" },\n * });\n */\n operatorSuffix?: Partial<Record<FilterOperator, string>>;\n}\n\n/**\n * Encode filters as query params for a paginated backend.\n *\n * The counterpart of {@link applyFilters}: same filter set, evaluated by the\n * database instead of by the browser, which is the only option once the list is\n * paginated on the server and the page in memory is not the whole result.\n *\n * The encoding is the `<column>__<op>` convention `tempest-fastapi-sdk` already\n * reads (`BaseRepository._apply_filters` → `build_filter_condition`):\n *\n * | Operator | Param |\n * | --- | --- |\n * | `eq` | `field` (or `field__iexact` for the `name` column) |\n * | `ne` | `field__ne` |\n * | `contains` | `field__icontains` |\n * | `gt` `gte` `lt` `lte` | `field__gt` … `field__lte` |\n * | `between` | `field__between` twice, low value first |\n * | `in` | `field__in` once per value |\n * | `empty` / `notEmpty` | `field__isnull=true` / `=false` |\n *\n * Returns `URLSearchParams` rather than a plain object because `between` carries\n * a pair and `in` carries a list: an object would keep only the last value of\n * each, silently narrowing the filter. Repeated params are also how FastAPI\n * receives a `list[str]` declared with `Query`.\n *\n * Two things the backend has to hold up its end of, or the filter fails quietly:\n *\n * - **Every key must be declared.** `BasePaginationFilterSchema.get_conditions()`\n * only forwards fields the subclass declares, so a `status__ne` the schema\n * never mentions is dropped by FastAPI before the repository sees it — no\n * error, no filtering.\n * - **`isnull` matches `NULL` only.** A column that stores `\"\"` for \"no value\"\n * will not answer an `empty` filter, while {@link applyFilters} treats blank\n * text as empty.\n *\n * The defaults are that dialect, not a universal truth. A backend that names its\n * substring column something other than `name`, or that spells its operators\n * differently, passes `options` — the alternative was an encoder whose special\n * cases were a wall for anyone not on the Tempest stack.\n *\n * @example\n * const params = filtersToQueryParams(filters);\n * params.set(\"page\", String(page));\n * const data = await api.get(`/orders?${params}`);\n *\n * @example\n * // A backend whose searchable column is `razao_social` and that spells `ne`\n * // the Django way.\n * const params = filtersToQueryParams(filters, {\n * substringColumns: [\"razao_social\"],\n * operatorSuffix: { ne: \"__exclude\" },\n * });\n *\n * @param filters - Applied filters; incomplete ones are ignored.\n * @param options - Dialect overrides. Defaults to the `tempest-fastapi-sdk` one.\n * @returns Params ready to append to a request URL.\n */\nexport function filtersToQueryParams(\n filters: readonly Filter[],\n options: FiltersToQueryParamsOptions = {},\n): URLSearchParams {\n const suffixes = options.operatorSuffix\n ? { ...DEFAULT_OPERATOR_SUFFIX, ...options.operatorSuffix }\n : DEFAULT_OPERATOR_SUFFIX;\n const substringColumns = options.substringColumns\n ? new Set(options.substringColumns)\n : DEFAULT_SUBSTRING_COLUMNS;\n\n const params = new URLSearchParams();\n\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n\n const suffix = suffixes[filter.operator];\n const key =\n filter.operator === \"eq\" && substringColumns.has(filter.field)\n ? `${filter.field}__iexact`\n : `${filter.field}${suffix}`;\n\n if (filter.operator === \"empty\" || filter.operator === \"notEmpty\") {\n params.append(key, filter.operator === \"empty\" ? \"true\" : \"false\");\n continue;\n }\n\n const values = Array.isArray(filter.value)\n ? [...filter.value]\n : [String(filter.value ?? \"\")];\n\n if (filter.operator === \"between\") {\n for (const value of orderRange(values)) params.append(key, value);\n continue;\n }\n\n for (const value of values) params.append(key, value);\n }\n\n return params;\n}\n"],"mappings":"A,sEAuBA,IAAMI,EAA0D,CAC5D,GAAI,GACJ,GAAI,OACJ,SAAU,cACV,GAAI,OACJ,IAAK,QACL,GAAI,OACJ,IAAK,QACL,QAAS,YACT,GAAI,OACJ,MAAO,WACP,SAAU,UACd,EAWMC,EAAiD,IAAI,IAAI,CAAC,MAAM,CAAC,EAqFvE,SAAgBC,EACZ,EACA,EAAuC,CAAC,EACzB,CACf,IAAMC,EAAWC,EAAQ,eACnB,CAAE,GAAGJ,EAAyB,GAAGI,EAAQ,cAAe,EACxDJ,EACAK,EAAmBD,EAAQ,iBAC3B,IAAI,IAAIA,EAAQ,gBAAgB,EAChCH,EAEAK,EAAS,IAAI,gBAEnB,IAAK,IAAMC,KAAUC,EAAS,CAC1B,GAAI,CAACZ,EAAAA,WAAWW,CAAM,EAAG,SAEzB,IAAME,EAASN,EAASI,EAAO,UACzBG,EACFH,EAAO,WAAa,MAAQF,EAAiB,IAAIE,EAAO,KAAK,EACvD,GAAGA,EAAO,MAAM,UAChB,GAAGA,EAAO,QAAQE,IAE5B,GAAIF,EAAO,WAAa,SAAWA,EAAO,WAAa,WAAY,CAC/DD,EAAO,OAAOI,EAAKH,EAAO,WAAa,QAAU,OAAS,OAAO,EACjE,QACJ,CAEA,IAAMI,EAAS,MAAM,QAAQJ,EAAO,KAAK,EACnC,CAAC,GAAGA,EAAO,KAAK,EAChB,CAAC,OAAOA,EAAO,OAAS,EAAE,CAAC,EAEjC,GAAIA,EAAO,WAAa,UACpB,IAAK,IAAMK,KAASf,EAAAA,WAAWc,CAAM,EAAGL,EAAO,OAAOI,EAAKE,CAAK,OAIpE,IAAK,IAAMA,KAASD,EAAQL,EAAO,OAAOI,EAAKE,CAAK,CACxD,CAEA,OAAON,CACX,C"}
@@ -27,11 +27,8 @@ function i(i, a = {}) {
27
27
  continue;
28
28
  }
29
29
  let a = Array.isArray(n.value) ? [...n.value] : [String(n.value ?? "")];
30
- if (n.operator === "between") {
31
- for (let e of t(a)) c.append(i, e);
32
- continue;
33
- }
34
- for (let e of a) c.append(i, e);
30
+ if (n.operator === "between") for (let e of t(a)) c.append(i, e);
31
+ else for (let e of a) c.append(i, e);
35
32
  }
36
33
  return c;
37
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"filter-query.js","names":[],"sources":["../../../src/components/FilterBar/filter-query.ts"],"sourcesContent":["// Server-side half of the filter model: the same `Filter[]` the bar produces,\n// encoded the way a paginated backend expects to read it. Kept apart from\n// `filtersToSearchParams` (filter-model.ts) because the two answer different\n// questions — that one round-trips the UI state through the URL, this one talks\n// to an API and its shape is the API's, not ours.\n\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\nimport { orderRange } from \"./filter-apply\";\n\n/**\n * Operator suffix per filter operator, following the `<column>__<op>` convention\n * of `tempest-fastapi-sdk`.\n *\n * Ported from `build_filter_condition` in\n * `tempest_fastapi_sdk/db/expressions.py`, which is what `BaseRepository`\n * dict filters and `Q` both resolve through. An empty suffix means the bare\n * column name, which that function resolves to plain equality.\n *\n * `contains` maps to `icontains` (case-insensitive, and the backend escapes the\n * `LIKE` wildcards) and both emptiness operators map to `isnull`, whose value\n * carries the direction.\n */\nconst DEFAULT_OPERATOR_SUFFIX: Record<FilterOperator, string> = {\n eq: \"\",\n ne: \"__ne\",\n contains: \"__icontains\",\n gt: \"__gt\",\n gte: \"__gte\",\n lt: \"__lt\",\n lte: \"__lte\",\n between: \"__between\",\n in: \"__in\",\n empty: \"__isnull\",\n notEmpty: \"__isnull\",\n};\n\n/**\n * Columns the backend treats as a substring search when they carry no operator\n * suffix.\n *\n * Ported from `build_filter_condition`, which special-cases a string `name` into\n * `ILIKE %value%`. Sending a bare `name=` for an `eq` filter would therefore ask\n * for \"contains\" while the chip says \"is\", so `eq` on such a column is emitted as\n * `name__iexact` instead.\n */\nconst DEFAULT_SUBSTRING_COLUMNS: ReadonlySet<string> = new Set([\"name\"]);\n\n/** Overrides for the backend dialect {@link filtersToQueryParams} encodes into. */\nexport interface FiltersToQueryParamsOptions {\n /**\n * Columns whose `eq` is emitted as `<column>__iexact` rather than as the bare\n * column name. Default `[\"name\"]`, which is what `build_filter_condition`\n * special-cases.\n *\n * Pass the columns **your** backend treats that way — `nome`, `titulo`,\n * `razao_social` — or `[]` when it treats none of them specially and a bare\n * `eq` should stay bare.\n */\n substringColumns?: readonly string[];\n /**\n * Operator suffixes, merged over the `tempest-fastapi-sdk` dialect, so an\n * override names only the operators that differ.\n *\n * @example\n * // A DRF-style backend\n * filtersToQueryParams(filters, {\n * substringColumns: [],\n * operatorSuffix: { contains: \"__icontains\", ne: \"__exclude\" },\n * });\n */\n operatorSuffix?: Partial<Record<FilterOperator, string>>;\n}\n\n/**\n * Encode filters as query params for a paginated backend.\n *\n * The counterpart of {@link applyFilters}: same filter set, evaluated by the\n * database instead of by the browser, which is the only option once the list is\n * paginated on the server and the page in memory is not the whole result.\n *\n * The encoding is the `<column>__<op>` convention `tempest-fastapi-sdk` already\n * reads (`BaseRepository._apply_filters` → `build_filter_condition`):\n *\n * | Operator | Param |\n * | --- | --- |\n * | `eq` | `field` (or `field__iexact` for the `name` column) |\n * | `ne` | `field__ne` |\n * | `contains` | `field__icontains` |\n * | `gt` `gte` `lt` `lte` | `field__gt` … `field__lte` |\n * | `between` | `field__between` twice, low value first |\n * | `in` | `field__in` once per value |\n * | `empty` / `notEmpty` | `field__isnull=true` / `=false` |\n *\n * Returns `URLSearchParams` rather than a plain object because `between` carries\n * a pair and `in` carries a list: an object would keep only the last value of\n * each, silently narrowing the filter. Repeated params are also how FastAPI\n * receives a `list[str]` declared with `Query`.\n *\n * Two things the backend has to hold up its end of, or the filter fails quietly:\n *\n * - **Every key must be declared.** `BasePaginationFilterSchema.get_conditions()`\n * only forwards fields the subclass declares, so a `status__ne` the schema\n * never mentions is dropped by FastAPI before the repository sees it — no\n * error, no filtering.\n * - **`isnull` matches `NULL` only.** A column that stores `\"\"` for \"no value\"\n * will not answer an `empty` filter, while {@link applyFilters} treats blank\n * text as empty.\n *\n * The defaults are that dialect, not a universal truth. A backend that names its\n * substring column something other than `name`, or that spells its operators\n * differently, passes `options` — the alternative was an encoder whose special\n * cases were a wall for anyone not on the Tempest stack.\n *\n * @example\n * const params = filtersToQueryParams(filters);\n * params.set(\"page\", String(page));\n * const data = await api.get(`/orders?${params}`);\n *\n * @example\n * // A backend whose searchable column is `razao_social` and that spells `ne`\n * // the Django way.\n * const params = filtersToQueryParams(filters, {\n * substringColumns: [\"razao_social\"],\n * operatorSuffix: { ne: \"__exclude\" },\n * });\n *\n * @param filters - Applied filters; incomplete ones are ignored.\n * @param options - Dialect overrides. Defaults to the `tempest-fastapi-sdk` one.\n * @returns Params ready to append to a request URL.\n */\nexport function filtersToQueryParams(\n filters: readonly Filter[],\n options: FiltersToQueryParamsOptions = {},\n): URLSearchParams {\n const suffixes = options.operatorSuffix\n ? { ...DEFAULT_OPERATOR_SUFFIX, ...options.operatorSuffix }\n : DEFAULT_OPERATOR_SUFFIX;\n const substringColumns = options.substringColumns\n ? new Set(options.substringColumns)\n : DEFAULT_SUBSTRING_COLUMNS;\n\n const params = new URLSearchParams();\n\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n\n const suffix = suffixes[filter.operator];\n const key =\n filter.operator === \"eq\" && substringColumns.has(filter.field)\n ? `${filter.field}__iexact`\n : `${filter.field}${suffix}`;\n\n if (filter.operator === \"empty\" || filter.operator === \"notEmpty\") {\n params.append(key, filter.operator === \"empty\" ? \"true\" : \"false\");\n continue;\n }\n\n const values = Array.isArray(filter.value)\n ? [...filter.value]\n : [String(filter.value ?? \"\")];\n\n if (filter.operator === \"between\") {\n for (const value of orderRange(values)) params.append(key, value);\n continue;\n }\n\n for (const value of values) params.append(key, value);\n }\n\n return params;\n}\n"],"mappings":";;;AAuBA,IAAM,IAA0D;CAC5D,IAAI;CACJ,IAAI;CACJ,UAAU;CACV,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,SAAS;CACT,IAAI;CACJ,OAAO;CACP,UAAU;AACd,GAWM,oBAAiD,IAAI,IAAI,CAAC,MAAM,CAAC;AAqFvE,SAAgB,EACZ,GACA,IAAuC,CAAC,GACzB;CACf,IAAM,IAAW,EAAQ,iBACnB;EAAE,GAAG;EAAyB,GAAG,EAAQ;CAAe,IACxD,GACA,IAAmB,EAAQ,mBAC3B,IAAI,IAAI,EAAQ,gBAAgB,IAChC,GAEA,IAAS,IAAI,gBAAgB;CAEnC,KAAK,IAAM,KAAU,GAAS;EAC1B,IAAI,CAAC,EAAW,CAAM,GAAG;EAEzB,IAAM,IAAS,EAAS,EAAO,WACzB,IACF,EAAO,aAAa,QAAQ,EAAiB,IAAI,EAAO,KAAK,IACvD,GAAG,EAAO,MAAM,YAChB,GAAG,EAAO,QAAQ;EAE5B,IAAI,EAAO,aAAa,WAAW,EAAO,aAAa,YAAY;GAC/D,EAAO,OAAO,GAAK,EAAO,aAAa,UAAU,SAAS,OAAO;GACjE;EACJ;EAEA,IAAM,IAAS,MAAM,QAAQ,EAAO,KAAK,IACnC,CAAC,GAAG,EAAO,KAAK,IAChB,CAAC,OAAO,EAAO,SAAS,EAAE,CAAC;EAEjC,IAAI,EAAO,aAAa,WAAW;GAC/B,KAAK,IAAM,KAAS,EAAW,CAAM,GAAG,EAAO,OAAO,GAAK,CAAK;GAChE;EACJ;EAEA,KAAK,IAAM,KAAS,GAAQ,EAAO,OAAO,GAAK,CAAK;CACxD;CAEA,OAAO;AACX"}
1
+ {"version":3,"file":"filter-query.js","names":["DEFAULT_OPERATOR_SUFFIX","DEFAULT_SUBSTRING_COLUMNS","filtersToQueryParams","suffixes","options","substringColumns","params","filter","filters","isComplete","suffix","key","values","value","orderRange"],"sources":["../../../src/components/FilterBar/filter-query.ts"],"sourcesContent":["// Server-side half of the filter model: the same `Filter[]` the bar produces,\n// encoded the way a paginated backend expects to read it. Kept apart from\n// `filtersToSearchParams` (filter-model.ts) because the two answer different\n// questions — that one round-trips the UI state through the URL, this one talks\n// to an API and its shape is the API's, not ours.\n\nimport type { Filter, FilterOperator } from \"./filter-model\";\nimport { isComplete } from \"./filter-model\";\nimport { orderRange } from \"./filter-apply\";\n\n/**\n * Operator suffix per filter operator, following the `<column>__<op>` convention\n * of `tempest-fastapi-sdk`.\n *\n * Ported from `build_filter_condition` in\n * `tempest_fastapi_sdk/db/expressions.py`, which is what `BaseRepository`\n * dict filters and `Q` both resolve through. An empty suffix means the bare\n * column name, which that function resolves to plain equality.\n *\n * `contains` maps to `icontains` (case-insensitive, and the backend escapes the\n * `LIKE` wildcards) and both emptiness operators map to `isnull`, whose value\n * carries the direction.\n */\nconst DEFAULT_OPERATOR_SUFFIX: Record<FilterOperator, string> = {\n eq: \"\",\n ne: \"__ne\",\n contains: \"__icontains\",\n gt: \"__gt\",\n gte: \"__gte\",\n lt: \"__lt\",\n lte: \"__lte\",\n between: \"__between\",\n in: \"__in\",\n empty: \"__isnull\",\n notEmpty: \"__isnull\",\n};\n\n/**\n * Columns the backend treats as a substring search when they carry no operator\n * suffix.\n *\n * Ported from `build_filter_condition`, which special-cases a string `name` into\n * `ILIKE %value%`. Sending a bare `name=` for an `eq` filter would therefore ask\n * for \"contains\" while the chip says \"is\", so `eq` on such a column is emitted as\n * `name__iexact` instead.\n */\nconst DEFAULT_SUBSTRING_COLUMNS: ReadonlySet<string> = new Set([\"name\"]);\n\n/** Overrides for the backend dialect {@link filtersToQueryParams} encodes into. */\nexport interface FiltersToQueryParamsOptions {\n /**\n * Columns whose `eq` is emitted as `<column>__iexact` rather than as the bare\n * column name. Default `[\"name\"]`, which is what `build_filter_condition`\n * special-cases.\n *\n * Pass the columns **your** backend treats that way — `nome`, `titulo`,\n * `razao_social` — or `[]` when it treats none of them specially and a bare\n * `eq` should stay bare.\n */\n substringColumns?: readonly string[];\n /**\n * Operator suffixes, merged over the `tempest-fastapi-sdk` dialect, so an\n * override names only the operators that differ.\n *\n * @example\n * // A DRF-style backend\n * filtersToQueryParams(filters, {\n * substringColumns: [],\n * operatorSuffix: { contains: \"__icontains\", ne: \"__exclude\" },\n * });\n */\n operatorSuffix?: Partial<Record<FilterOperator, string>>;\n}\n\n/**\n * Encode filters as query params for a paginated backend.\n *\n * The counterpart of {@link applyFilters}: same filter set, evaluated by the\n * database instead of by the browser, which is the only option once the list is\n * paginated on the server and the page in memory is not the whole result.\n *\n * The encoding is the `<column>__<op>` convention `tempest-fastapi-sdk` already\n * reads (`BaseRepository._apply_filters` → `build_filter_condition`):\n *\n * | Operator | Param |\n * | --- | --- |\n * | `eq` | `field` (or `field__iexact` for the `name` column) |\n * | `ne` | `field__ne` |\n * | `contains` | `field__icontains` |\n * | `gt` `gte` `lt` `lte` | `field__gt` … `field__lte` |\n * | `between` | `field__between` twice, low value first |\n * | `in` | `field__in` once per value |\n * | `empty` / `notEmpty` | `field__isnull=true` / `=false` |\n *\n * Returns `URLSearchParams` rather than a plain object because `between` carries\n * a pair and `in` carries a list: an object would keep only the last value of\n * each, silently narrowing the filter. Repeated params are also how FastAPI\n * receives a `list[str]` declared with `Query`.\n *\n * Two things the backend has to hold up its end of, or the filter fails quietly:\n *\n * - **Every key must be declared.** `BasePaginationFilterSchema.get_conditions()`\n * only forwards fields the subclass declares, so a `status__ne` the schema\n * never mentions is dropped by FastAPI before the repository sees it — no\n * error, no filtering.\n * - **`isnull` matches `NULL` only.** A column that stores `\"\"` for \"no value\"\n * will not answer an `empty` filter, while {@link applyFilters} treats blank\n * text as empty.\n *\n * The defaults are that dialect, not a universal truth. A backend that names its\n * substring column something other than `name`, or that spells its operators\n * differently, passes `options` — the alternative was an encoder whose special\n * cases were a wall for anyone not on the Tempest stack.\n *\n * @example\n * const params = filtersToQueryParams(filters);\n * params.set(\"page\", String(page));\n * const data = await api.get(`/orders?${params}`);\n *\n * @example\n * // A backend whose searchable column is `razao_social` and that spells `ne`\n * // the Django way.\n * const params = filtersToQueryParams(filters, {\n * substringColumns: [\"razao_social\"],\n * operatorSuffix: { ne: \"__exclude\" },\n * });\n *\n * @param filters - Applied filters; incomplete ones are ignored.\n * @param options - Dialect overrides. Defaults to the `tempest-fastapi-sdk` one.\n * @returns Params ready to append to a request URL.\n */\nexport function filtersToQueryParams(\n filters: readonly Filter[],\n options: FiltersToQueryParamsOptions = {},\n): URLSearchParams {\n const suffixes = options.operatorSuffix\n ? { ...DEFAULT_OPERATOR_SUFFIX, ...options.operatorSuffix }\n : DEFAULT_OPERATOR_SUFFIX;\n const substringColumns = options.substringColumns\n ? new Set(options.substringColumns)\n : DEFAULT_SUBSTRING_COLUMNS;\n\n const params = new URLSearchParams();\n\n for (const filter of filters) {\n if (!isComplete(filter)) continue;\n\n const suffix = suffixes[filter.operator];\n const key =\n filter.operator === \"eq\" && substringColumns.has(filter.field)\n ? `${filter.field}__iexact`\n : `${filter.field}${suffix}`;\n\n if (filter.operator === \"empty\" || filter.operator === \"notEmpty\") {\n params.append(key, filter.operator === \"empty\" ? \"true\" : \"false\");\n continue;\n }\n\n const values = Array.isArray(filter.value)\n ? [...filter.value]\n : [String(filter.value ?? \"\")];\n\n if (filter.operator === \"between\") {\n for (const value of orderRange(values)) params.append(key, value);\n continue;\n }\n\n for (const value of values) params.append(key, value);\n }\n\n return params;\n}\n"],"mappings":";;;AAuBA,IAAMA,IAA0D;CAC5D,IAAI;CACJ,IAAI;CACJ,UAAU;CACV,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,SAAS;CACT,IAAI;CACJ,OAAO;CACP,UAAU;AACd,GAWMC,oBAAiD,IAAI,IAAI,CAAC,MAAM,CAAC;AAqFvE,SAAgBC,EACZ,GACA,IAAuC,CAAC,GACzB;CACf,IAAMC,IAAWC,EAAQ,iBACnB;EAAE,GAAGJ;EAAyB,GAAGI,EAAQ;CAAe,IACxDJ,GACAK,IAAmBD,EAAQ,mBAC3B,IAAI,IAAIA,EAAQ,gBAAgB,IAChCH,GAEAK,IAAS,IAAI,gBAAgB;CAEnC,KAAK,IAAMC,KAAUC,GAAS;EAC1B,IAAI,CAACC,EAAWF,CAAM,GAAG;EAEzB,IAAMG,IAASP,EAASI,EAAO,WACzBI,IACFJ,EAAO,aAAa,QAAQF,EAAiB,IAAIE,EAAO,KAAK,IACvD,GAAGA,EAAO,MAAM,YAChB,GAAGA,EAAO,QAAQG;EAE5B,IAAIH,EAAO,aAAa,WAAWA,EAAO,aAAa,YAAY;GAC/D,EAAO,OAAOI,GAAKJ,EAAO,aAAa,UAAU,SAAS,OAAO;GACjE;EACJ;EAEA,IAAMK,IAAS,MAAM,QAAQL,EAAO,KAAK,IACnC,CAAC,GAAGA,EAAO,KAAK,IAChB,CAAC,OAAOA,EAAO,SAAS,EAAE,CAAC;EAEjC,IAAIA,EAAO,aAAa,WACpB,KAAK,IAAMM,KAASC,EAAWF,CAAM,GAAG,EAAO,OAAOD,GAAKE,CAAK;OAIpE,KAAK,IAAMA,KAASD,GAAQ,EAAO,OAAOD,GAAKE,CAAK;CACxD;CAEA,OAAOP;AACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterPanel.cjs","names":[],"sources":["../../../src/components/FilterPanel/FilterPanel.tsx"],"sourcesContent":["import {\n useId,\n type CSSProperties,\n type FormEvent,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { Button } from \"../Button\";\nimport { Card } from \"../Card\";\nimport { Grid, type ResponsiveValue } from \"../Layout\";\nimport styles from \"./FilterPanel.module.css\";\n\n/** Labels the panel writes itself. */\nexport interface FilterPanelLabels {\n /** Default title. `\"Filtros\"` / `\"Filters\"`. */\n title: string;\n /** The clear button. `\"Limpar filtros\"` / `\"Clear filters\"`. */\n clear: string;\n /** The apply button. `\"Filtrar\"` / `\"Apply filters\"`. */\n apply: string;\n}\n\n/** Built-in labels per locale. */\nconst LABELS: Record<\"pt-BR\" | \"en\", FilterPanelLabels> = {\n \"pt-BR\": { title: \"Filtros\", clear: \"Limpar filtros\", apply: \"Filtrar\" },\n en: { title: \"Filters\", clear: \"Clear filters\", apply: \"Apply filters\" },\n};\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"title\" | \"children\" | \"onSubmit\";\n\nexport interface FilterPanelProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** The filter controls the screen declares — `Input`, `Select`, a date picker. One grid cell each. */\n children: ReactNode;\n /** Heading. Default from `locale`. A string renders as an `h3`; a node renders as given. */\n title?: ReactNode;\n /** Header actions that are not fields — \"Atualizar a cada 30s\", \"Exportar CSV\". */\n actions?: ReactNode;\n /** Return the screen to its initial filters. Renders the clear button only when set. */\n onClear?: () => void;\n /**\n * Publish the draft. When set, the fields sit in a `<form>`: the apply button\n * submits it and Enter in any text field applies.\n */\n onApply?: () => void;\n /**\n * Disable the apply button — pass `!filters.isDirty`. Enter follows the button:\n * it is the form's default button, so a disabled one blocks implicit submission\n * too, and nothing is re-applied when nothing changed.\n */\n applyDisabled?: boolean;\n /** Locale for the default title and button labels. Default `\"pt-BR\"`. */\n locale?: \"pt-BR\" | \"en\";\n /** Override any of the labels. */\n labels?: Partial<FilterPanelLabels>;\n /**\n * Narrowest a field may get before the grid drops a column. Default `\"12rem\"`.\n * The count follows the **panel's** width, so the same panel fits a page and a\n * sidebar.\n */\n minFieldWidth?: string;\n /**\n * Fixed columns per viewport, as in `Grid` — `{ mobile: 1, tablet: 2, desktop: 4 }`.\n * Replaces `minFieldWidth`, and follows the **viewport**, not the panel.\n */\n columns?: ResponsiveValue<number | string>;\n}\n\n/**\n * The frame around a fixed set of filters: a card with a title, a grid of the\n * fields the screen declares, and the actions that belong to no field — clear,\n * apply, export.\n *\n * It holds no state and has no opinion on the fields. `FilterBar` is for ad hoc\n * querying (the user picks field, operator and value); this is for the set a\n * screen already knows — município, UF, situação, a search box. Pair it with\n * `useDraftFilters`: the fields edit `draft`, `onApply` and `onClear` are the\n * hook's `apply` and `clear`.\n *\n * What it settles, each measured in Chromium against the `Card` + `Grid`\n * composition it replaces:\n *\n * - **The grid follows the panel, not the viewport.** `Grid` switches columns on\n * viewport breakpoints, so the same filters in a 360 px column of a 1280 px\n * screen got four 57.5 px fields. The default here is\n * `repeat(auto-fill, minmax(min(100%, minFieldWidth), 1fr))`: the column count\n * comes from the room the panel has, and `min(100%, …)` keeps a floor wider than\n * the phone from overflowing it.\n * - **Cells align to the top.** A field showing an error is taller; with the grid\n * default (`stretch`), its row-mates' boxes grew to match.\n * - **The header wraps.** Three actions next to the title measured 527 px in a\n * 308 px header at 390 px wide, and scrolled the whole page sideways. `Card`'s\n * header now wraps, and so do the actions inside it.\n * - **Clear and apply have a fixed place**, at the end of the header, apply last.\n *\n * @example\n * const filters = useDraftFilters({ search: \"\", uf: \"\" });\n * <FilterPanel\n * onApply={() => filters.apply()}\n * onClear={filters.clear}\n * applyDisabled={!filters.isDirty}\n * >\n * <Input label=\"Busca\" value={filters.draft.search}\n * onChange={(e) => filters.set({ search: e.target.value })} />\n * <Select label=\"UF\" options={UFS} value={filters.draft.uf}\n * onChange={(e) => filters.set({ uf: e.target.value })} />\n * </FilterPanel>\n */\nexport function FilterPanel({\n children,\n title,\n actions,\n onClear,\n onApply,\n applyDisabled = false,\n locale = \"pt-BR\",\n labels,\n minFieldWidth = \"12rem\",\n columns,\n className,\n style,\n ...props\n}: FilterPanelProps) {\n const formId = useId();\n const text: FilterPanelLabels = { ...LABELS[locale], ...labels };\n const heading = title ?? text.title;\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>): void => {\n event.preventDefault();\n onApply?.();\n };\n\n const hasActions = actions !== undefined || onClear !== undefined || onApply !== undefined;\n const headerActions = hasActions ? (\n <div className={styles.actions}>\n {actions}\n {onClear && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onClear}>\n {text.clear}\n </Button>\n )}\n {onApply && (\n <Button type=\"submit\" size=\"sm\" form={formId} disabled={applyDisabled}>\n {text.apply}\n </Button>\n )}\n </div>\n ) : undefined;\n\n const fields = (\n <Grid\n className={styles.fields}\n columns={\n columns ??\n \"repeat(auto-fill, minmax(min(100%, var(--tempest-filter-panel-min)), 1fr))\"\n }\n >\n {children}\n </Grid>\n );\n\n return (\n <Card\n flush\n role=\"search\"\n aria-label={typeof heading === \"string\" ? heading : undefined}\n title={heading}\n actions={headerActions}\n className={cn(styles.panel, className)}\n style={{ \"--tempest-filter-panel-min\": minFieldWidth, ...style } as CSSProperties}\n {...props}\n >\n {onApply ? (\n <form id={formId} className={styles.form} onSubmit={handleSubmit} noValidate>\n {fields}\n </form>\n ) : (\n fields\n )}\n </Card>\n );\n}\n"],"mappings":"oOA0BA,IAAM,EAAoD,CACtD,QAAS,CAAE,MAAO,UAAW,MAAO,iBAAkB,MAAO,SAAU,EACvE,GAAI,CAAE,MAAO,UAAW,MAAO,gBAAiB,MAAO,eAAgB,CAC3E,EAkFA,SAAgB,EAAY,CACxB,WACA,QACA,UACA,UACA,UACA,gBAAgB,GAChB,SAAS,QACT,SACA,gBAAgB,QAChB,UACA,YACA,QACA,GAAG,GACc,CACjB,IAAM,GAAA,EAAS,EAAA,MAAA,CAAM,EACf,EAA0B,CAAE,GAAG,EAAO,GAAS,GAAG,CAAO,EACzD,EAAU,GAAS,EAAK,MAExB,EAAgB,GAA4C,CAC9D,EAAM,eAAe,EACrB,IAAU,CACd,EAGM,EADa,IAAY,IAAA,IAAa,IAAY,IAAA,IAAa,IAAY,IAAA,IAE7E,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,QAAvB,SAAA,CACK,EACA,IACG,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAK,SAAS,QAAQ,QAAQ,KAAK,KAAK,QAAS,EACpD,SAAA,EAAK,KACF,CAAA,EAEX,IACG,EAAA,EAAA,IAAA,CAAC,EAAA,OAAD,CAAQ,KAAK,SAAS,KAAK,KAAK,KAAM,EAAQ,SAAU,EACnD,SAAA,EAAK,KACF,CAAA,CAEX,CACL,CAAA,EAAA,IAAA,GAEE,GACF,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CACI,UAAW,EAAA,QAAO,OAClB,QACI,GACA,6EAGH,UACC,CAAA,EAGV,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,KAAD,CACI,MAAA,GACA,KAAK,SACL,aAAY,OAAO,GAAY,SAAW,EAAU,IAAA,GACpD,MAAO,EACP,QAAS,EACT,UAAW,EAAA,GAAG,EAAA,QAAO,MAAO,CAAS,EACrC,MAAO,CAAE,6BAA8B,EAAe,GAAG,CAAM,EAC/D,GAAI,EAEH,SAAA,GACG,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,GAAI,EAAQ,UAAW,EAAA,QAAO,KAAM,SAAU,EAAc,WAAA,GAC7D,SAAA,CACC,CAAA,EAEN,CAEF,CAAA,CAEd"}
1
+ {"version":3,"file":"FilterPanel.cjs","names":["useId","styles","Button","Grid","Card","cn","require_cn","require_Button","require_Card","require_Layout","require_FilterPanel_module","react","react_jsx_runtime","LABELS","FilterPanel","props","formId","text","locale","labels","heading","title","handleSubmit","event","onApply","headerActions","actions","onClear","applyDisabled","fields","columns","className","minFieldWidth","style"],"sources":["../../../src/components/FilterPanel/FilterPanel.tsx"],"sourcesContent":["import {\n useId,\n type CSSProperties,\n type FormEvent,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { Button } from \"../Button\";\nimport { Card } from \"../Card\";\nimport { Grid, type ResponsiveValue } from \"../Layout\";\nimport styles from \"./FilterPanel.module.css\";\n\n/** Labels the panel writes itself. */\nexport interface FilterPanelLabels {\n /** Default title. `\"Filtros\"` / `\"Filters\"`. */\n title: string;\n /** The clear button. `\"Limpar filtros\"` / `\"Clear filters\"`. */\n clear: string;\n /** The apply button. `\"Filtrar\"` / `\"Apply filters\"`. */\n apply: string;\n}\n\n/** Built-in labels per locale. */\nconst LABELS: Record<\"pt-BR\" | \"en\", FilterPanelLabels> = {\n \"pt-BR\": { title: \"Filtros\", clear: \"Limpar filtros\", apply: \"Filtrar\" },\n en: { title: \"Filters\", clear: \"Clear filters\", apply: \"Apply filters\" },\n};\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"title\" | \"children\" | \"onSubmit\";\n\nexport interface FilterPanelProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** The filter controls the screen declares — `Input`, `Select`, a date picker. One grid cell each. */\n children: ReactNode;\n /** Heading. Default from `locale`. A string renders as an `h3`; a node renders as given. */\n title?: ReactNode;\n /** Header actions that are not fields — \"Atualizar a cada 30s\", \"Exportar CSV\". */\n actions?: ReactNode;\n /** Return the screen to its initial filters. Renders the clear button only when set. */\n onClear?: () => void;\n /**\n * Publish the draft. When set, the fields sit in a `<form>`: the apply button\n * submits it and Enter in any text field applies.\n */\n onApply?: () => void;\n /**\n * Disable the apply button — pass `!filters.isDirty`. Enter follows the button:\n * it is the form's default button, so a disabled one blocks implicit submission\n * too, and nothing is re-applied when nothing changed.\n */\n applyDisabled?: boolean;\n /** Locale for the default title and button labels. Default `\"pt-BR\"`. */\n locale?: \"pt-BR\" | \"en\";\n /** Override any of the labels. */\n labels?: Partial<FilterPanelLabels>;\n /**\n * Narrowest a field may get before the grid drops a column. Default `\"12rem\"`.\n * The count follows the **panel's** width, so the same panel fits a page and a\n * sidebar.\n */\n minFieldWidth?: string;\n /**\n * Fixed columns per viewport, as in `Grid` — `{ mobile: 1, tablet: 2, desktop: 4 }`.\n * Replaces `minFieldWidth`, and follows the **viewport**, not the panel.\n */\n columns?: ResponsiveValue<number | string>;\n}\n\n/**\n * The frame around a fixed set of filters: a card with a title, a grid of the\n * fields the screen declares, and the actions that belong to no field — clear,\n * apply, export.\n *\n * It holds no state and has no opinion on the fields. `FilterBar` is for ad hoc\n * querying (the user picks field, operator and value); this is for the set a\n * screen already knows — município, UF, situação, a search box. Pair it with\n * `useDraftFilters`: the fields edit `draft`, `onApply` and `onClear` are the\n * hook's `apply` and `clear`.\n *\n * What it settles, each measured in Chromium against the `Card` + `Grid`\n * composition it replaces:\n *\n * - **The grid follows the panel, not the viewport.** `Grid` switches columns on\n * viewport breakpoints, so the same filters in a 360 px column of a 1280 px\n * screen got four 57.5 px fields. The default here is\n * `repeat(auto-fill, minmax(min(100%, minFieldWidth), 1fr))`: the column count\n * comes from the room the panel has, and `min(100%, …)` keeps a floor wider than\n * the phone from overflowing it.\n * - **Cells align to the top.** A field showing an error is taller; with the grid\n * default (`stretch`), its row-mates' boxes grew to match.\n * - **The header wraps.** Three actions next to the title measured 527 px in a\n * 308 px header at 390 px wide, and scrolled the whole page sideways. `Card`'s\n * header now wraps, and so do the actions inside it.\n * - **Clear and apply have a fixed place**, at the end of the header, apply last.\n *\n * @example\n * const filters = useDraftFilters({ search: \"\", uf: \"\" });\n * <FilterPanel\n * onApply={() => filters.apply()}\n * onClear={filters.clear}\n * applyDisabled={!filters.isDirty}\n * >\n * <Input label=\"Busca\" value={filters.draft.search}\n * onChange={(e) => filters.set({ search: e.target.value })} />\n * <Select label=\"UF\" options={UFS} value={filters.draft.uf}\n * onChange={(e) => filters.set({ uf: e.target.value })} />\n * </FilterPanel>\n */\nexport function FilterPanel({\n children,\n title,\n actions,\n onClear,\n onApply,\n applyDisabled = false,\n locale = \"pt-BR\",\n labels,\n minFieldWidth = \"12rem\",\n columns,\n className,\n style,\n ...props\n}: FilterPanelProps) {\n const formId = useId();\n const text: FilterPanelLabels = { ...LABELS[locale], ...labels };\n const heading = title ?? text.title;\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>): void => {\n event.preventDefault();\n onApply?.();\n };\n\n const hasActions = actions !== undefined || onClear !== undefined || onApply !== undefined;\n const headerActions = hasActions ? (\n <div className={styles.actions}>\n {actions}\n {onClear && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onClear}>\n {text.clear}\n </Button>\n )}\n {onApply && (\n <Button type=\"submit\" size=\"sm\" form={formId} disabled={applyDisabled}>\n {text.apply}\n </Button>\n )}\n </div>\n ) : undefined;\n\n const fields = (\n <Grid\n className={styles.fields}\n columns={\n columns ??\n \"repeat(auto-fill, minmax(min(100%, var(--tempest-filter-panel-min)), 1fr))\"\n }\n >\n {children}\n </Grid>\n );\n\n return (\n <Card\n flush\n role=\"search\"\n aria-label={typeof heading === \"string\" ? heading : undefined}\n title={heading}\n actions={headerActions}\n className={cn(styles.panel, className)}\n style={{ \"--tempest-filter-panel-min\": minFieldWidth, ...style } as CSSProperties}\n {...props}\n >\n {onApply ? (\n <form id={formId} className={styles.form} onSubmit={handleSubmit} noValidate>\n {fields}\n </form>\n ) : (\n fields\n )}\n </Card>\n );\n}\n"],"mappings":"A,oOA0BA,IAAMa,EAAoD,CACtD,QAAS,CAAE,MAAO,UAAW,MAAO,iBAAkB,MAAO,SAAU,EACvE,GAAI,CAAE,MAAO,UAAW,MAAO,gBAAiB,MAAO,eAAgB,CAC3E,EAkFA,SAAgBC,EAAY,CACxB,WACA,QACA,UACA,UACA,UACA,gBAAgB,GAChB,SAAS,QACT,SACA,gBAAgB,QAChB,UACA,YACA,QACA,GAAGC,GACc,CACjB,IAAMC,GAAA,EAAShB,EAAAA,MAAAA,CAAM,EACfiB,EAA0B,CAAE,GAAGJ,EAAOK,GAAS,GAAGC,CAAO,EACzDC,EAAUC,GAASJ,EAAK,MAExBK,EAAgB,GAA4C,CAC9DC,EAAM,eAAe,EACrBC,IAAU,CACd,EAGMC,EADaC,IAAY,IAAA,IAAaC,IAAY,IAAA,IAAaH,IAAY,IAAA,IAE7E,EAAAZ,EAAA,KAAA,CAAC,MAAD,CAAK,UAAWX,EAAAA,QAAO,QAAvB,SAAA,CACKyB,EACAC,IACG,EAAAf,EAAA,IAAA,CAACV,EAAAA,OAAD,CAAQ,KAAK,SAAS,QAAQ,QAAQ,KAAK,KAAK,QAASyB,EACpD,SAAAV,EAAK,KACF,CAAA,EAEXO,IACG,EAAAZ,EAAA,IAAA,CAACV,EAAAA,OAAD,CAAQ,KAAK,SAAS,KAAK,KAAK,KAAMc,EAAQ,SAAUY,EACnD,SAAAX,EAAK,KACF,CAAA,CAEX,CACL,CAAA,EAAA,IAAA,GAEEY,GACF,EAAAjB,EAAA,IAAA,CAACT,EAAAA,KAAD,CACI,UAAWF,EAAAA,QAAO,OAClB,QACI6B,GACA,6EAGH,UACC,CAAA,EAGV,OACI,EAAAlB,EAAA,IAAA,CAACR,EAAAA,KAAD,CACI,MAAA,GACA,KAAK,SACL,aAAY,OAAOgB,GAAY,SAAWA,EAAU,IAAA,GACpD,MAAOA,EACP,QAASK,EACT,UAAWpB,EAAAA,GAAGJ,EAAAA,QAAO,MAAO8B,CAAS,EACrC,MAAO,CAAE,6BAA8BC,EAAe,GAAGC,CAAM,EAC/D,GAAIlB,EAEH,SAAAS,GACG,EAAAZ,EAAA,IAAA,CAAC,OAAD,CAAM,GAAII,EAAQ,UAAWf,EAAAA,QAAO,KAAM,SAAUqB,EAAc,WAAA,GAC7D,SAAAO,CACC,CAAA,EAENA,CAEF,CAAA,CAEd,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterPanel.js","names":[],"sources":["../../../src/components/FilterPanel/FilterPanel.tsx"],"sourcesContent":["import {\n useId,\n type CSSProperties,\n type FormEvent,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { Button } from \"../Button\";\nimport { Card } from \"../Card\";\nimport { Grid, type ResponsiveValue } from \"../Layout\";\nimport styles from \"./FilterPanel.module.css\";\n\n/** Labels the panel writes itself. */\nexport interface FilterPanelLabels {\n /** Default title. `\"Filtros\"` / `\"Filters\"`. */\n title: string;\n /** The clear button. `\"Limpar filtros\"` / `\"Clear filters\"`. */\n clear: string;\n /** The apply button. `\"Filtrar\"` / `\"Apply filters\"`. */\n apply: string;\n}\n\n/** Built-in labels per locale. */\nconst LABELS: Record<\"pt-BR\" | \"en\", FilterPanelLabels> = {\n \"pt-BR\": { title: \"Filtros\", clear: \"Limpar filtros\", apply: \"Filtrar\" },\n en: { title: \"Filters\", clear: \"Clear filters\", apply: \"Apply filters\" },\n};\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"title\" | \"children\" | \"onSubmit\";\n\nexport interface FilterPanelProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** The filter controls the screen declares — `Input`, `Select`, a date picker. One grid cell each. */\n children: ReactNode;\n /** Heading. Default from `locale`. A string renders as an `h3`; a node renders as given. */\n title?: ReactNode;\n /** Header actions that are not fields — \"Atualizar a cada 30s\", \"Exportar CSV\". */\n actions?: ReactNode;\n /** Return the screen to its initial filters. Renders the clear button only when set. */\n onClear?: () => void;\n /**\n * Publish the draft. When set, the fields sit in a `<form>`: the apply button\n * submits it and Enter in any text field applies.\n */\n onApply?: () => void;\n /**\n * Disable the apply button — pass `!filters.isDirty`. Enter follows the button:\n * it is the form's default button, so a disabled one blocks implicit submission\n * too, and nothing is re-applied when nothing changed.\n */\n applyDisabled?: boolean;\n /** Locale for the default title and button labels. Default `\"pt-BR\"`. */\n locale?: \"pt-BR\" | \"en\";\n /** Override any of the labels. */\n labels?: Partial<FilterPanelLabels>;\n /**\n * Narrowest a field may get before the grid drops a column. Default `\"12rem\"`.\n * The count follows the **panel's** width, so the same panel fits a page and a\n * sidebar.\n */\n minFieldWidth?: string;\n /**\n * Fixed columns per viewport, as in `Grid` — `{ mobile: 1, tablet: 2, desktop: 4 }`.\n * Replaces `minFieldWidth`, and follows the **viewport**, not the panel.\n */\n columns?: ResponsiveValue<number | string>;\n}\n\n/**\n * The frame around a fixed set of filters: a card with a title, a grid of the\n * fields the screen declares, and the actions that belong to no field — clear,\n * apply, export.\n *\n * It holds no state and has no opinion on the fields. `FilterBar` is for ad hoc\n * querying (the user picks field, operator and value); this is for the set a\n * screen already knows — município, UF, situação, a search box. Pair it with\n * `useDraftFilters`: the fields edit `draft`, `onApply` and `onClear` are the\n * hook's `apply` and `clear`.\n *\n * What it settles, each measured in Chromium against the `Card` + `Grid`\n * composition it replaces:\n *\n * - **The grid follows the panel, not the viewport.** `Grid` switches columns on\n * viewport breakpoints, so the same filters in a 360 px column of a 1280 px\n * screen got four 57.5 px fields. The default here is\n * `repeat(auto-fill, minmax(min(100%, minFieldWidth), 1fr))`: the column count\n * comes from the room the panel has, and `min(100%, …)` keeps a floor wider than\n * the phone from overflowing it.\n * - **Cells align to the top.** A field showing an error is taller; with the grid\n * default (`stretch`), its row-mates' boxes grew to match.\n * - **The header wraps.** Three actions next to the title measured 527 px in a\n * 308 px header at 390 px wide, and scrolled the whole page sideways. `Card`'s\n * header now wraps, and so do the actions inside it.\n * - **Clear and apply have a fixed place**, at the end of the header, apply last.\n *\n * @example\n * const filters = useDraftFilters({ search: \"\", uf: \"\" });\n * <FilterPanel\n * onApply={() => filters.apply()}\n * onClear={filters.clear}\n * applyDisabled={!filters.isDirty}\n * >\n * <Input label=\"Busca\" value={filters.draft.search}\n * onChange={(e) => filters.set({ search: e.target.value })} />\n * <Select label=\"UF\" options={UFS} value={filters.draft.uf}\n * onChange={(e) => filters.set({ uf: e.target.value })} />\n * </FilterPanel>\n */\nexport function FilterPanel({\n children,\n title,\n actions,\n onClear,\n onApply,\n applyDisabled = false,\n locale = \"pt-BR\",\n labels,\n minFieldWidth = \"12rem\",\n columns,\n className,\n style,\n ...props\n}: FilterPanelProps) {\n const formId = useId();\n const text: FilterPanelLabels = { ...LABELS[locale], ...labels };\n const heading = title ?? text.title;\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>): void => {\n event.preventDefault();\n onApply?.();\n };\n\n const hasActions = actions !== undefined || onClear !== undefined || onApply !== undefined;\n const headerActions = hasActions ? (\n <div className={styles.actions}>\n {actions}\n {onClear && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onClear}>\n {text.clear}\n </Button>\n )}\n {onApply && (\n <Button type=\"submit\" size=\"sm\" form={formId} disabled={applyDisabled}>\n {text.apply}\n </Button>\n )}\n </div>\n ) : undefined;\n\n const fields = (\n <Grid\n className={styles.fields}\n columns={\n columns ??\n \"repeat(auto-fill, minmax(min(100%, var(--tempest-filter-panel-min)), 1fr))\"\n }\n >\n {children}\n </Grid>\n );\n\n return (\n <Card\n flush\n role=\"search\"\n aria-label={typeof heading === \"string\" ? heading : undefined}\n title={heading}\n actions={headerActions}\n className={cn(styles.panel, className)}\n style={{ \"--tempest-filter-panel-min\": minFieldWidth, ...style } as CSSProperties}\n {...props}\n >\n {onApply ? (\n <form id={formId} className={styles.form} onSubmit={handleSubmit} noValidate>\n {fields}\n </form>\n ) : (\n fields\n )}\n </Card>\n );\n}\n"],"mappings":";;;;;;;;AA0BA,IAAM,IAAoD;CACtD,SAAS;EAAE,OAAO;EAAW,OAAO;EAAkB,OAAO;CAAU;CACvE,IAAI;EAAE,OAAO;EAAW,OAAO;EAAiB,OAAO;CAAgB;AAC3E;AAkFA,SAAgB,EAAY,EACxB,aACA,UACA,YACA,YACA,YACA,mBAAgB,IAChB,YAAS,SACT,WACA,mBAAgB,SAChB,YACA,cACA,UACA,GAAG,KACc;CACjB,IAAM,IAAS,EAAM,GACf,IAA0B;EAAE,GAAG,EAAO;EAAS,GAAG;CAAO,GACzD,IAAU,KAAS,EAAK,OAExB,KAAgB,MAA4C;EAE9D,AADA,EAAM,eAAe,GACrB,IAAU;CACd,GAGM,IADa,MAAY,KAAA,KAAa,MAAY,KAAA,KAAa,MAAY,KAAA,IAE7E,kBAAC,OAAD;EAAK,WAAW,EAAO;EAAvB,UAAA;GACK;GACA,KACG,kBAAC,GAAD;IAAQ,MAAK;IAAS,SAAQ;IAAQ,MAAK;IAAK,SAAS;IACpD,UAAA,EAAK;GACF,CAAA;GAEX,KACG,kBAAC,GAAD;IAAQ,MAAK;IAAS,MAAK;IAAK,MAAM;IAAQ,UAAU;IACnD,UAAA,EAAK;GACF,CAAA;EAEX;CACL,CAAA,IAAA,KAAA,GAEE,IACF,kBAAC,GAAD;EACI,WAAW,EAAO;EAClB,SACI,KACA;EAGH;CACC,CAAA;CAGV,OACI,kBAAC,GAAD;EACI,OAAA;EACA,MAAK;EACL,cAAY,OAAO,KAAY,WAAW,IAAU,KAAA;EACpD,OAAO;EACP,SAAS;EACT,WAAW,EAAG,EAAO,OAAO,CAAS;EACrC,OAAO;GAAE,8BAA8B;GAAe,GAAG;EAAM;EAC/D,GAAI;EAEH,UAAA,IACG,kBAAC,QAAD;GAAM,IAAI;GAAQ,WAAW,EAAO;GAAM,UAAU;GAAc,YAAA;GAC7D,UAAA;EACC,CAAA,IAEN;CAEF,CAAA;AAEd"}
1
+ {"version":3,"file":"FilterPanel.js","names":["styles","FilterPanel_module_default","LABELS","FilterPanel","props","formId","useId","text","locale","labels","heading","title","handleSubmit","event","onApply","headerActions","actions","onClear","Button","applyDisabled","fields","Grid","columns","Card","cn","className","minFieldWidth","style"],"sources":["../../../src/components/FilterPanel/FilterPanel.tsx"],"sourcesContent":["import {\n useId,\n type CSSProperties,\n type FormEvent,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nimport { Button } from \"../Button\";\nimport { Card } from \"../Card\";\nimport { Grid, type ResponsiveValue } from \"../Layout\";\nimport styles from \"./FilterPanel.module.css\";\n\n/** Labels the panel writes itself. */\nexport interface FilterPanelLabels {\n /** Default title. `\"Filtros\"` / `\"Filters\"`. */\n title: string;\n /** The clear button. `\"Limpar filtros\"` / `\"Clear filters\"`. */\n clear: string;\n /** The apply button. `\"Filtrar\"` / `\"Apply filters\"`. */\n apply: string;\n}\n\n/** Built-in labels per locale. */\nconst LABELS: Record<\"pt-BR\" | \"en\", FilterPanelLabels> = {\n \"pt-BR\": { title: \"Filtros\", clear: \"Limpar filtros\", apply: \"Filtrar\" },\n en: { title: \"Filters\", clear: \"Clear filters\", apply: \"Apply filters\" },\n};\n\n/** DOM attributes this component redefines. */\ntype OverriddenDomProps = \"title\" | \"children\" | \"onSubmit\";\n\nexport interface FilterPanelProps extends Omit<HTMLAttributes<HTMLDivElement>, OverriddenDomProps> {\n /** The filter controls the screen declares — `Input`, `Select`, a date picker. One grid cell each. */\n children: ReactNode;\n /** Heading. Default from `locale`. A string renders as an `h3`; a node renders as given. */\n title?: ReactNode;\n /** Header actions that are not fields — \"Atualizar a cada 30s\", \"Exportar CSV\". */\n actions?: ReactNode;\n /** Return the screen to its initial filters. Renders the clear button only when set. */\n onClear?: () => void;\n /**\n * Publish the draft. When set, the fields sit in a `<form>`: the apply button\n * submits it and Enter in any text field applies.\n */\n onApply?: () => void;\n /**\n * Disable the apply button — pass `!filters.isDirty`. Enter follows the button:\n * it is the form's default button, so a disabled one blocks implicit submission\n * too, and nothing is re-applied when nothing changed.\n */\n applyDisabled?: boolean;\n /** Locale for the default title and button labels. Default `\"pt-BR\"`. */\n locale?: \"pt-BR\" | \"en\";\n /** Override any of the labels. */\n labels?: Partial<FilterPanelLabels>;\n /**\n * Narrowest a field may get before the grid drops a column. Default `\"12rem\"`.\n * The count follows the **panel's** width, so the same panel fits a page and a\n * sidebar.\n */\n minFieldWidth?: string;\n /**\n * Fixed columns per viewport, as in `Grid` — `{ mobile: 1, tablet: 2, desktop: 4 }`.\n * Replaces `minFieldWidth`, and follows the **viewport**, not the panel.\n */\n columns?: ResponsiveValue<number | string>;\n}\n\n/**\n * The frame around a fixed set of filters: a card with a title, a grid of the\n * fields the screen declares, and the actions that belong to no field — clear,\n * apply, export.\n *\n * It holds no state and has no opinion on the fields. `FilterBar` is for ad hoc\n * querying (the user picks field, operator and value); this is for the set a\n * screen already knows — município, UF, situação, a search box. Pair it with\n * `useDraftFilters`: the fields edit `draft`, `onApply` and `onClear` are the\n * hook's `apply` and `clear`.\n *\n * What it settles, each measured in Chromium against the `Card` + `Grid`\n * composition it replaces:\n *\n * - **The grid follows the panel, not the viewport.** `Grid` switches columns on\n * viewport breakpoints, so the same filters in a 360 px column of a 1280 px\n * screen got four 57.5 px fields. The default here is\n * `repeat(auto-fill, minmax(min(100%, minFieldWidth), 1fr))`: the column count\n * comes from the room the panel has, and `min(100%, …)` keeps a floor wider than\n * the phone from overflowing it.\n * - **Cells align to the top.** A field showing an error is taller; with the grid\n * default (`stretch`), its row-mates' boxes grew to match.\n * - **The header wraps.** Three actions next to the title measured 527 px in a\n * 308 px header at 390 px wide, and scrolled the whole page sideways. `Card`'s\n * header now wraps, and so do the actions inside it.\n * - **Clear and apply have a fixed place**, at the end of the header, apply last.\n *\n * @example\n * const filters = useDraftFilters({ search: \"\", uf: \"\" });\n * <FilterPanel\n * onApply={() => filters.apply()}\n * onClear={filters.clear}\n * applyDisabled={!filters.isDirty}\n * >\n * <Input label=\"Busca\" value={filters.draft.search}\n * onChange={(e) => filters.set({ search: e.target.value })} />\n * <Select label=\"UF\" options={UFS} value={filters.draft.uf}\n * onChange={(e) => filters.set({ uf: e.target.value })} />\n * </FilterPanel>\n */\nexport function FilterPanel({\n children,\n title,\n actions,\n onClear,\n onApply,\n applyDisabled = false,\n locale = \"pt-BR\",\n labels,\n minFieldWidth = \"12rem\",\n columns,\n className,\n style,\n ...props\n}: FilterPanelProps) {\n const formId = useId();\n const text: FilterPanelLabels = { ...LABELS[locale], ...labels };\n const heading = title ?? text.title;\n\n const handleSubmit = (event: FormEvent<HTMLFormElement>): void => {\n event.preventDefault();\n onApply?.();\n };\n\n const hasActions = actions !== undefined || onClear !== undefined || onApply !== undefined;\n const headerActions = hasActions ? (\n <div className={styles.actions}>\n {actions}\n {onClear && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onClear}>\n {text.clear}\n </Button>\n )}\n {onApply && (\n <Button type=\"submit\" size=\"sm\" form={formId} disabled={applyDisabled}>\n {text.apply}\n </Button>\n )}\n </div>\n ) : undefined;\n\n const fields = (\n <Grid\n className={styles.fields}\n columns={\n columns ??\n \"repeat(auto-fill, minmax(min(100%, var(--tempest-filter-panel-min)), 1fr))\"\n }\n >\n {children}\n </Grid>\n );\n\n return (\n <Card\n flush\n role=\"search\"\n aria-label={typeof heading === \"string\" ? heading : undefined}\n title={heading}\n actions={headerActions}\n className={cn(styles.panel, className)}\n style={{ \"--tempest-filter-panel-min\": minFieldWidth, ...style } as CSSProperties}\n {...props}\n >\n {onApply ? (\n <form id={formId} className={styles.form} onSubmit={handleSubmit} noValidate>\n {fields}\n </form>\n ) : (\n fields\n )}\n </Card>\n );\n}\n"],"mappings":";;;;;;;;AA0BA,IAAME,IAAoD;CACtD,SAAS;EAAE,OAAO;EAAW,OAAO;EAAkB,OAAO;CAAU;CACvE,IAAI;EAAE,OAAO;EAAW,OAAO;EAAiB,OAAO;CAAgB;AAC3E;AAkFA,SAAgBC,EAAY,EACxB,aACA,UACA,YACA,YACA,YACA,mBAAgB,IAChB,YAAS,SACT,WACA,mBAAgB,SAChB,YACA,cACA,UACA,GAAGC,KACc;CACjB,IAAMC,IAASC,EAAM,GACfC,IAA0B;EAAE,GAAGL,EAAOM;EAAS,GAAGC;CAAO,GACzDC,IAAUC,KAASJ,EAAK,OAExBK,KAAgB,MAA4C;EAE9D,AADAC,EAAM,eAAe,GACrBC,IAAU;CACd,GAGMC,IADaC,MAAY,KAAA,KAAaC,MAAY,KAAA,KAAaH,MAAY,KAAA,IAE7E,kBAAC,OAAD;EAAK,WAAWd,EAAO;EAAvB,UAAA;GACKgB;GACAC,KACG,kBAACC,GAAD;IAAQ,MAAK;IAAS,SAAQ;IAAQ,MAAK;IAAK,SAASD;IACpD,UAAAV,EAAK;GACF,CAAA;GAEXO,KACG,kBAACI,GAAD;IAAQ,MAAK;IAAS,MAAK;IAAK,MAAMb;IAAQ,UAAUc;IACnD,UAAAZ,EAAK;GACF,CAAA;EAEX;CACL,CAAA,IAAA,KAAA,GAEEa,IACF,kBAACC,GAAD;EACI,WAAWrB,EAAO;EAClB,SACIsB,KACA;EAGH;CACC,CAAA;CAGV,OACI,kBAACC,GAAD;EACI,OAAA;EACA,MAAK;EACL,cAAY,OAAOb,KAAY,WAAWA,IAAU,KAAA;EACpD,OAAOA;EACP,SAASK;EACT,WAAWS,EAAGxB,EAAO,OAAOyB,CAAS;EACrC,OAAO;GAAE,8BAA8BC;GAAe,GAAGC;EAAM;EAC/D,GAAIvB;EAEH,UAAAU,IACG,kBAAC,QAAD;GAAM,IAAIT;GAAQ,WAAWL,EAAO;GAAM,UAAUY;GAAc,YAAA;GAC7D,UAAAQ;EACC,CAAA,IAENA;CAEF,CAAA;AAEd"}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterPanel.module.cjs","names":[],"sources":["../../../src/components/FilterPanel/FilterPanel.module.css"],"sourcesContent":[".panel {\n min-width: 0;\n}\n\n/*\n * Actions share the header row with the title on a wide screen and move under it,\n * wrapping among themselves, when they do not fit. Apply stays last.\n */\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--tempest-space-2);\n margin-left: auto;\n}\n\n.form {\n margin: 0;\n}\n\n/*\n * Top alignment keeps a field's box its own height: the grid default stretches every\n * cell of a row to the tallest one, which is the field showing an error.\n */\n.fields {\n align-items: start;\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"FilterPanel.module.cjs","names":["panel","actions","form","fields","FilterPanel_module_default"],"sources":["../../../src/components/FilterPanel/FilterPanel.module.css"],"sourcesContent":[".panel {\n min-width: 0;\n}\n\n/*\n * Actions share the header row with the title on a wide screen and move under it,\n * wrapping among themselves, when they do not fit. Apply stays last.\n */\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--tempest-space-2);\n margin-left: auto;\n}\n\n.form {\n margin: 0;\n}\n\n/*\n * Top alignment keeps a field's box its own height: the grid default stretches every\n * cell of a row to the tallest one, which is the field showing an error.\n */\n.fields {\n align-items: start;\n}\n"],"mappings":";"}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterPanel.module.js","names":[],"sources":["../../../src/components/FilterPanel/FilterPanel.module.css"],"sourcesContent":[".panel {\n min-width: 0;\n}\n\n/*\n * Actions share the header row with the title on a wide screen and move under it,\n * wrapping among themselves, when they do not fit. Apply stays last.\n */\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--tempest-space-2);\n margin-left: auto;\n}\n\n.form {\n margin: 0;\n}\n\n/*\n * Top alignment keeps a field's box its own height: the grid default stretches every\n * cell of a row to the tallest one, which is the field showing an error.\n */\n.fields {\n align-items: start;\n}\n"],"mappings":";"}
1
+ {"version":3,"file":"FilterPanel.module.js","names":["panel","actions","form","fields","FilterPanel_module_default"],"sources":["../../../src/components/FilterPanel/FilterPanel.module.css"],"sourcesContent":[".panel {\n min-width: 0;\n}\n\n/*\n * Actions share the header row with the title on a wide screen and move under it,\n * wrapping among themselves, when they do not fit. Apply stays last.\n */\n.actions {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: var(--tempest-space-2);\n margin-left: auto;\n}\n\n.form {\n margin: 0;\n}\n\n/*\n * Top alignment keeps a field's box its own height: the grid default stretches every\n * cell of a row to the tallest one, which is the field showing an error.\n */\n.fields {\n align-items: start;\n}\n"],"mappings":";"}
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingActionButton.cjs","names":[],"sources":["../../../src/components/FloatingActionButton/FloatingActionButton.tsx"],"sourcesContent":["import type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./FloatingActionButton.module.css\";\n\nexport type FloatingActionButtonPosition = \"bottom-right\" | \"bottom-left\" | \"none\";\nexport type FloatingActionButtonSize = \"sm\" | \"md\" | \"lg\";\nexport type FloatingActionButtonVariant = \"primary\" | \"surface\";\n\nexport interface FloatingActionButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Icon rendered inside the FAB. Required. */\n icon: ReactNode;\n /** When present, renders an extended (pill) FAB with icon + label. */\n label?: ReactNode;\n /** Corner placement, or `\"none\"` for static/inline. Default `\"bottom-right\"`. */\n position?: FloatingActionButtonPosition;\n /** Size token. Default `\"md\"`. */\n size?: FloatingActionButtonSize;\n /** Visual style. Default `\"primary\"`. */\n variant?: FloatingActionButtonVariant;\n /** Extra class names merged onto the root. */\n className?: string;\n}\n\n/**\n * Material Floating Action Button. Renders a round FAB when only an `icon` is\n * given, or an extended pill FAB when a `label` is also provided. By default it\n * is fixed to the bottom-right corner; set `position=\"none\"` to place it inline.\n *\n * Spreads all native `<button>` props (`onClick`, `disabled`, etc.).\n *\n * @remarks\n * Always pass an `aria-label` when there is no `label`, since an icon-only FAB\n * has no accessible name otherwise.\n *\n * @example\n * <FloatingActionButton icon={<Plus />} aria-label=\"Adicionar\" onClick={create} />\n *\n * @example\n * <FloatingActionButton icon={<Plus />} label=\"Novo\" onClick={create} />\n */\nexport function FloatingActionButton({\n icon,\n label,\n position = \"bottom-right\",\n size = \"md\",\n variant = \"primary\",\n className,\n ...props\n}: FloatingActionButtonProps) {\n const extended = label !== undefined;\n return (\n <button\n type=\"button\"\n className={cn(\n styles.fab,\n styles[size],\n styles[variant],\n extended ? styles.extended : styles.round,\n position !== \"none\" && styles.fixed,\n position === \"bottom-right\" && styles.bottomRight,\n position === \"bottom-left\" && styles.bottomLeft,\n className,\n )}\n {...props}\n >\n <span className={styles.icon}>{icon}</span>\n {extended && <span className={styles.label}>{label}</span>}\n </button>\n );\n}\n"],"mappings":"wHAwCA,SAAgB,EAAqB,CACjC,OACA,QACA,WAAW,eACX,OAAO,KACP,UAAU,UACV,YACA,GAAG,GACuB,CAC1B,IAAM,EAAW,IAAU,IAAA,GAC3B,OACI,EAAA,EAAA,KAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAW,EAAA,GACP,EAAA,QAAO,IACP,EAAA,QAAO,GACP,EAAA,QAAO,GACP,EAAW,EAAA,QAAO,SAAW,EAAA,QAAO,MACpC,IAAa,QAAU,EAAA,QAAO,MAC9B,IAAa,gBAAkB,EAAA,QAAO,YACtC,IAAa,eAAiB,EAAA,QAAO,WACrC,CACJ,EACA,GAAI,EAZR,SAAA,EAcI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,KAAO,SAAA,CAAW,CAAA,EACzC,IAAY,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,CAAY,CAAA,CACrD,GAEhB"}
1
+ {"version":3,"file":"FloatingActionButton.cjs","names":["cn","styles","require_cn","require_FloatingActionButton_module","react_jsx_runtime","FloatingActionButton","props","extended","label","size","variant","position","className","icon"],"sources":["../../../src/components/FloatingActionButton/FloatingActionButton.tsx"],"sourcesContent":["import type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport styles from \"./FloatingActionButton.module.css\";\n\nexport type FloatingActionButtonPosition = \"bottom-right\" | \"bottom-left\" | \"none\";\nexport type FloatingActionButtonSize = \"sm\" | \"md\" | \"lg\";\nexport type FloatingActionButtonVariant = \"primary\" | \"surface\";\n\nexport interface FloatingActionButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n /** Icon rendered inside the FAB. Required. */\n icon: ReactNode;\n /** When present, renders an extended (pill) FAB with icon + label. */\n label?: ReactNode;\n /** Corner placement, or `\"none\"` for static/inline. Default `\"bottom-right\"`. */\n position?: FloatingActionButtonPosition;\n /** Size token. Default `\"md\"`. */\n size?: FloatingActionButtonSize;\n /** Visual style. Default `\"primary\"`. */\n variant?: FloatingActionButtonVariant;\n /** Extra class names merged onto the root. */\n className?: string;\n}\n\n/**\n * Material Floating Action Button. Renders a round FAB when only an `icon` is\n * given, or an extended pill FAB when a `label` is also provided. By default it\n * is fixed to the bottom-right corner; set `position=\"none\"` to place it inline.\n *\n * Spreads all native `<button>` props (`onClick`, `disabled`, etc.).\n *\n * @remarks\n * Always pass an `aria-label` when there is no `label`, since an icon-only FAB\n * has no accessible name otherwise.\n *\n * @example\n * <FloatingActionButton icon={<Plus />} aria-label=\"Adicionar\" onClick={create} />\n *\n * @example\n * <FloatingActionButton icon={<Plus />} label=\"Novo\" onClick={create} />\n */\nexport function FloatingActionButton({\n icon,\n label,\n position = \"bottom-right\",\n size = \"md\",\n variant = \"primary\",\n className,\n ...props\n}: FloatingActionButtonProps) {\n const extended = label !== undefined;\n return (\n <button\n type=\"button\"\n className={cn(\n styles.fab,\n styles[size],\n styles[variant],\n extended ? styles.extended : styles.round,\n position !== \"none\" && styles.fixed,\n position === \"bottom-right\" && styles.bottomRight,\n position === \"bottom-left\" && styles.bottomLeft,\n className,\n )}\n {...props}\n >\n <span className={styles.icon}>{icon}</span>\n {extended && <span className={styles.label}>{label}</span>}\n </button>\n );\n}\n"],"mappings":"A,wHAwCA,SAAgBK,EAAqB,CACjC,OACA,QACA,WAAW,eACX,OAAO,KACP,UAAU,UACV,YACA,GAAGC,GACuB,CAC1B,IAAMC,EAAWC,IAAU,IAAA,GAC3B,OACI,EAAAJ,EAAA,KAAA,CAAC,SAAD,CACI,KAAK,SACL,UAAWJ,EAAAA,GACPC,EAAAA,QAAO,IACPA,EAAAA,QAAOQ,GACPR,EAAAA,QAAOS,GACPH,EAAWN,EAAAA,QAAO,SAAWA,EAAAA,QAAO,MACpCU,IAAa,QAAUV,EAAAA,QAAO,MAC9BU,IAAa,gBAAkBV,EAAAA,QAAO,YACtCU,IAAa,eAAiBV,EAAAA,QAAO,WACrCW,CACJ,EACA,GAAIN,EAZR,SAAA,EAcI,EAAAF,EAAA,IAAA,CAAC,OAAD,CAAM,UAAWH,EAAAA,QAAO,KAAO,SAAAY,CAAW,CAAA,EACzCN,IAAY,EAAAH,EAAA,IAAA,CAAC,OAAD,CAAM,UAAWH,EAAAA,QAAO,MAAQ,SAAAO,CAAY,CAAA,CACrD,C,EAEhB,C"}