@hot-updater/console 1.0.0-rc.2 → 1.0.0-rc.21

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 (285) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/ConsoleFeatureUnavailable-D0LPL1Gy.js +1 -0
  3. package/.output/public/assets/HashValueDisplay-BmuB4FW-.js +1 -0
  4. package/.output/public/assets/InsightsInfo--v4SC07c.js +1 -0
  5. package/.output/public/assets/InsightsPageHeader-dU83CAQY.js +1 -0
  6. package/.output/public/assets/NotFoundPage-B5mhGG2a.js +1 -0
  7. package/.output/public/assets/api-D-vOVlQ4.js +1 -0
  8. package/.output/public/assets/api-keys-Csh8ARKU.js +1 -0
  9. package/.output/public/assets/api-keys-OMPUoA_A.js +1 -0
  10. package/.output/public/assets/arrow-left-Bwq9X1eS.js +1 -0
  11. package/.output/public/assets/arrow-up-right-BkOVn4if.js +1 -0
  12. package/.output/public/assets/card-C_7d6O9a.js +1 -0
  13. package/.output/public/assets/console-features-api-C1jRZTGw.js +1 -0
  14. package/.output/public/assets/dialog-DE8wFN_P.js +1 -0
  15. package/.output/public/assets/dist-C7ENGzpS.js +1 -0
  16. package/.output/public/assets/empty-CVd5NlQD.js +1 -0
  17. package/.output/public/assets/field-C06q1iC9.js +1 -0
  18. package/.output/public/assets/index-BeWlQtO6.js +11 -0
  19. package/.output/public/assets/input-group-Bi61biIA.js +1 -0
  20. package/.output/public/assets/insights-BjnAtC0f.js +2 -0
  21. package/.output/public/assets/insights-D86m11yH.js +42 -0
  22. package/.output/public/assets/insights-DpYstMoY.js +1 -0
  23. package/.output/public/assets/insights-recovery-rpc-BIm5_ALc.js +1 -0
  24. package/.output/public/assets/insights-search-KIF7mRtB.js +1 -0
  25. package/.output/public/assets/insights-usage-rpc-VHj8vyBt.js +1 -0
  26. package/.output/public/assets/insights_.distribution-ADcrX48c.js +2 -0
  27. package/.output/public/assets/insights_.distribution-CuuJUN6Y.js +1 -0
  28. package/.output/public/assets/insights_.distribution-DJRjuXsO.js +1 -0
  29. package/.output/public/assets/installations-BSBBzqWs.js +2 -0
  30. package/.output/public/assets/installations-DqIE6WcO.js +1 -0
  31. package/.output/public/assets/installations-UsELbDvw.js +1 -0
  32. package/.output/public/assets/loader-circle-CnCBxzHp.js +1 -0
  33. package/.output/public/assets/mutation-Csp7xUNh.js +1 -0
  34. package/.output/public/assets/preload-helper-B-cOmpLH.js +1 -0
  35. package/.output/public/assets/refresh-cw-FF1NtzlQ.js +1 -0
  36. package/.output/public/assets/routes-CoN9XHP_.js +2 -0
  37. package/.output/public/assets/routes-DT1jB0Zi.js +1 -0
  38. package/.output/public/assets/sidebar-D8mJRF15.js +3 -0
  39. package/.output/public/assets/styles-Bwt7v6U5.css +2 -0
  40. package/.output/public/assets/table-WBgfvgXg.js +1 -0
  41. package/.output/public/assets/useCompositeListItem-CloBmDwn.js +1 -0
  42. package/.output/public/assets/useMutation-DO8cvsTx.js +1 -0
  43. package/.output/public/assets/useOpenInteractionType-ReGr9GzJ.js +1 -0
  44. package/.output/public/assets/valueToPercent-BvPAi4bP.js +1 -0
  45. package/.output/server/{__23tanstack-start-server-fn-resolver-B7ioJhtE.mjs → __23tanstack-start-server-fn-resolver-DMRD4e4f.mjs} +51 -47
  46. package/.output/server/_libs/@base-ui/react+[...].mjs +7044 -3622
  47. package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1554 -0
  48. package/.output/server/_libs/@tanstack/react-router+[...].mjs +3803 -4023
  49. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +141 -98
  50. package/.output/server/_libs/d3-array.mjs +231 -0
  51. package/.output/server/_libs/d3-color.mjs +330 -0
  52. package/.output/server/_libs/d3-format.mjs +252 -0
  53. package/.output/server/_libs/d3-interpolate.mjs +207 -0
  54. package/.output/server/_libs/d3-path.mjs +77 -0
  55. package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
  56. package/.output/server/_libs/d3-shape.mjs +818 -0
  57. package/.output/server/_libs/decimal.js-light.mjs +884 -0
  58. package/.output/server/_libs/es-toolkit.mjs +1159 -0
  59. package/.output/server/_libs/eventemitter3.mjs +236 -0
  60. package/.output/server/_libs/immer.mjs +532 -0
  61. package/.output/server/_libs/lucide-react.mjs +46 -32
  62. package/.output/server/_libs/next-themes.mjs +2 -2
  63. package/.output/server/_libs/react-redux+[...].mjs +205 -0
  64. package/.output/server/_libs/recharts+[...].mjs +14350 -0
  65. package/.output/server/_libs/sonner.mjs +2 -2
  66. package/.output/server/_libs/tanstack__history.mjs +68 -41
  67. package/.output/server/_libs/tanstack__query-core.mjs +1618 -309
  68. package/.output/server/_libs/tanstack__react-query.mjs +262 -22
  69. package/.output/server/_libs/verkit.mjs +99 -1
  70. package/.output/server/_runtime.mjs +10 -1
  71. package/.output/server/_ssr/ConsoleFeatureUnavailable-Du7jNPNS.mjs +58 -0
  72. package/.output/server/_ssr/{HashValueDisplay-DwpGLfrl.mjs → HashValueDisplay-GQvFkXoi.mjs} +3 -3
  73. package/.output/server/_ssr/InsightsInfo-Do7QSaFR.mjs +37 -0
  74. package/.output/server/_ssr/InsightsPageHeader-DSUWUWRc.mjs +154 -0
  75. package/.output/server/_ssr/NotFoundPage-DsF4Vrhg.mjs +37 -0
  76. package/.output/server/_ssr/api-BEiVs0H7.mjs +203 -0
  77. package/.output/server/_ssr/api-keys-BrvBWGRf.mjs +5 -0
  78. package/.output/server/_ssr/{api-keys-CZeTPQys.mjs → api-keys-K5v32nf7.mjs} +49 -9
  79. package/.output/server/_ssr/api-keys-rpc-B96bBllm.mjs +52 -0
  80. package/.output/server/_ssr/api-rpc-DcUe280B.mjs +296 -0
  81. package/.output/server/_ssr/{auth-rpc-DUaeOWKK.mjs → auth-rpc-C68W56DP.mjs} +6 -6
  82. package/.output/server/_ssr/auth.server-DM1J6NwR.mjs +5712 -0
  83. package/.output/server/_ssr/bundleActivity-CpuY9CTP.mjs +19 -0
  84. package/.output/server/_ssr/card-CPAEKx0w.mjs +49 -0
  85. package/.output/server/_ssr/config-nsIcsHh8.mjs +15 -0
  86. package/.output/server/_ssr/config.server-DDCZk3Sq.mjs +36 -0
  87. package/.output/server/_ssr/console-access-Da-2Qd7q.mjs +17 -0
  88. package/.output/server/_ssr/console-features-Dzu2iUGD.mjs +55 -0
  89. package/.output/server/_ssr/console-features-api-xAsSgFa_.mjs +43 -0
  90. package/.output/server/_ssr/console-features-rpc-qARGpB24.mjs +19 -0
  91. package/.output/server/_ssr/{createServerFn-B2hcXoPM.mjs → createMiddleware-BdBf_ezN.mjs} +67 -56
  92. package/.output/server/_ssr/{createServerRpc-DB29C_5p.mjs → createServerRpc-B_y2lrwA.mjs} +2 -2
  93. package/.output/server/_ssr/{databaseJsonValue-d6I3nAS4.mjs → databaseJsonValue-Bhxciy7Z.mjs} +28 -5
  94. package/.output/server/_ssr/databaseRows-DwMAjaF8.mjs +74 -0
  95. package/.output/server/_ssr/{dialog-DS-nw-pA.mjs → dialog-q__BJ7mQ.mjs} +2 -2
  96. package/.output/server/_ssr/{dist-CyzPaI5v.mjs → dist-Cxo9ghYv.mjs} +140 -6
  97. package/.output/server/_ssr/{downloadBundle-CNnYxYO2.mjs → downloadBundle-BW9I-pMQ.mjs} +10 -10
  98. package/.output/server/_ssr/empty-DcBTAooP.mjs +49 -0
  99. package/.output/server/_ssr/{empty-plugin-adapters-B5QvGpEl.mjs → empty-plugin-adapters-CYdinE-i.mjs} +1 -1
  100. package/.output/server/_ssr/{table-CnZmon_Z.mjs → field-QCDBVpXA.mjs} +63 -51
  101. package/.output/server/_ssr/getBundleChildren-DIAGCF4a.mjs +22 -0
  102. package/.output/server/_ssr/{input-group-BpsnmvZw.mjs → input-group-hCk2nUoU.mjs} +2 -2
  103. package/.output/server/_ssr/insights-BfBO0RFr.mjs +1238 -0
  104. package/.output/server/_ssr/insights-DsAU3-TB.mjs +14 -0
  105. package/.output/server/_ssr/insights-RIfg447W.mjs +5 -0
  106. package/.output/server/_ssr/insights-api-CDn-QQHU.mjs +105 -0
  107. package/.output/server/_ssr/insights-failures-BBGMhuUr.mjs +44 -0
  108. package/.output/server/_ssr/insights-failures-rpc-rA2dctK2.mjs +21 -0
  109. package/.output/server/_ssr/insights-recovery-Dpk6Mfb9.mjs +28 -0
  110. package/.output/server/_ssr/insights-recovery-rpc-BCaF-xSd.mjs +46 -0
  111. package/.output/server/_ssr/insights-recovery-rpc-CcgYyUHk.mjs +20 -0
  112. package/.output/server/_ssr/{insights-rpc-38DujK0G.mjs → insights-rpc-keycmwzw.mjs} +22 -14
  113. package/.output/server/_ssr/insights-search-BRg5VsNe.mjs +25 -0
  114. package/.output/server/_ssr/insights-usage-cbw9n2Fq.mjs +29 -0
  115. package/.output/server/_ssr/insights-usage-rpc-BKgV1QDf.mjs +29 -0
  116. package/.output/server/_ssr/insights-usage-rpc-D-JYachy.mjs +41 -0
  117. package/.output/server/_ssr/insightsRecovery-B7oMc8d8.mjs +45 -0
  118. package/.output/server/_ssr/insightsUsage-Oa7kk5ek.mjs +56 -0
  119. package/.output/server/_ssr/insights_.distribution-BIqOqRW0.mjs +335 -0
  120. package/.output/server/_ssr/insights_.distribution-CuUrDa7P.mjs +5 -0
  121. package/.output/server/_ssr/insights_.distribution-RT_6x_ud.mjs +14 -0
  122. package/.output/server/_ssr/{installations-DiVKEF5T.mjs → installations-BO5CjX2z.mjs} +517 -54
  123. package/.output/server/_ssr/installations-BjaHiIfh.mjs +5 -0
  124. package/.output/server/_ssr/installations-Dt5luA-N.mjs +69 -0
  125. package/.output/server/_ssr/listReleases-BitHzOYB.mjs +79 -0
  126. package/.output/server/_ssr/releaseManagement-B3e7I8J9.mjs +11 -0
  127. package/.output/server/_ssr/{router-B9wG_9f8.mjs → router-DfVAixxe.mjs} +135 -139
  128. package/.output/server/_ssr/{routes-D7Yh_jfj.mjs → routes-C6LstNp8.mjs} +176 -455
  129. package/.output/server/_ssr/routes-Q3Uhmwwz.mjs +292 -0
  130. package/.output/server/_ssr/runtime.server-fL0o6I2b.mjs +1459 -0
  131. package/.output/server/_ssr/schema-BKY9SqaY.mjs +25 -0
  132. package/.output/server/_ssr/select-CUlInmjk.mjs +107 -0
  133. package/.output/server/_ssr/server-C43wq9ft.mjs +8330 -0
  134. package/.output/server/_ssr/{createSsrRpc-DjWNJ0uc.mjs → sidebar-DKbx2ach.mjs} +117 -63
  135. package/.output/server/_ssr/ssr.mjs +1 -1
  136. package/.output/server/_ssr/start-BXUOv_n8.mjs +4 -0
  137. package/.output/server/_ssr/table-NGWV8B-S.mjs +53 -0
  138. package/.output/server/_ssr/updateFailures-Jwe2Baab.mjs +24 -0
  139. package/.output/server/_ssr/{uuidv7-D0QFkPL_.mjs → uuidv7-C8bwiZr8.mjs} +2 -2
  140. package/.output/server/_tanstack-start-manifest_v-WQ5qGn8n.mjs +124 -0
  141. package/.output/server/index.mjs +267 -162
  142. package/LICENSE +13 -14
  143. package/README.md +82 -72
  144. package/lib/index.d.mts +23 -11
  145. package/lib/vite-internal.mjs +13 -3
  146. package/lib/vite.d.mts +2 -0
  147. package/package.json +14 -14
  148. package/src/components/AppSidebar.tsx +100 -71
  149. package/src/components/ConsoleAccessPage.tsx +5 -1
  150. package/src/components/ConsoleFeatureUnavailable.tsx +80 -0
  151. package/src/components/NotFoundPage.tsx +7 -7
  152. package/src/components/features/FeatureSlots.tsx +99 -0
  153. package/src/components/features/api-keys/apiKeysFeatureUi.tsx +15 -0
  154. package/src/components/features/bundles/BundleMetadata.tsx +8 -5
  155. package/src/components/features/bundles/RolloutCohortsDialog.tsx +1 -1
  156. package/src/components/features/channels/ChannelManagementDialog.tsx +2 -5
  157. package/src/components/features/insights/AppUsage.tsx +370 -0
  158. package/src/components/features/insights/EstimatedCount.tsx +18 -0
  159. package/src/components/features/insights/EventDetails.tsx +117 -37
  160. package/src/components/features/insights/EventHistoryCard.tsx +112 -26
  161. package/src/components/features/insights/EventHistoryList.tsx +2 -2
  162. package/src/components/features/insights/InsightsControls.tsx +265 -102
  163. package/src/components/features/insights/InsightsErrorAlert.tsx +14 -1
  164. package/src/components/features/insights/InsightsInfo.tsx +48 -0
  165. package/src/components/features/insights/InsightsOverview.tsx +176 -173
  166. package/src/components/features/insights/InsightsPageHeader.tsx +35 -20
  167. package/src/components/features/insights/InsightsPeriodSelector.tsx +89 -0
  168. package/src/components/features/insights/InstallationHistoryCard.tsx +52 -10
  169. package/src/components/features/insights/InstallationMatchesCard.tsx +1 -1
  170. package/src/components/features/insights/ReleaseActivity.tsx +188 -0
  171. package/src/components/features/insights/ReportingDevicesSummary.tsx +65 -0
  172. package/src/components/features/insights/UpdateFailures.tsx +319 -0
  173. package/src/components/features/insights/insightsFeatureUi.tsx +35 -0
  174. package/src/components/features/releases/ReleaseEditorSheet.tsx +30 -7
  175. package/src/components/ui/card.tsx +1 -1
  176. package/src/components/ui/empty.tsx +101 -0
  177. package/src/components/ui/scroll-area.tsx +52 -0
  178. package/src/components/ui/sidebar.tsx +22 -29
  179. package/src/components/ui/tabs.tsx +81 -0
  180. package/src/index.ts +26 -19
  181. package/src/lib/api-keys-api.ts +0 -28
  182. package/src/lib/api-keys-rpc.ts +27 -38
  183. package/src/lib/api-rpc.ts +189 -266
  184. package/src/lib/api.ts +19 -102
  185. package/src/lib/bundle-activity.ts +31 -0
  186. package/src/lib/console-access.ts +20 -0
  187. package/src/lib/console-features-api.ts +68 -0
  188. package/src/lib/console-features-rpc.ts +13 -0
  189. package/src/lib/console-features.ts +91 -0
  190. package/src/lib/insights-api.ts +37 -1
  191. package/src/lib/insights-failures-rpc.ts +21 -0
  192. package/src/lib/insights-failures.ts +129 -0
  193. package/src/lib/insights-recovery-rpc.ts +51 -0
  194. package/src/lib/insights-recovery.ts +68 -0
  195. package/src/lib/insights-retention.ts +21 -0
  196. package/src/lib/insights-rpc.ts +30 -12
  197. package/src/lib/insights-search.ts +58 -0
  198. package/src/lib/insights-usage-rpc.ts +29 -0
  199. package/src/lib/insights-usage.ts +74 -0
  200. package/src/lib/insights-view.ts +38 -2
  201. package/src/lib/scroll-restoration.ts +21 -0
  202. package/src/lib/server/adminInsights.ts +124 -0
  203. package/src/lib/server/auth.server.ts +13 -5
  204. package/src/lib/server/bundleActivity.ts +37 -0
  205. package/src/lib/server/config.server.ts +21 -74
  206. package/src/lib/server/console-feature-apis.ts +59 -0
  207. package/src/lib/server/console-runtime.server.ts +82 -38
  208. package/src/lib/server/downloadBundle.ts +16 -15
  209. package/src/lib/server/getBundleChildren.ts +31 -122
  210. package/src/lib/server/insightsRecovery.ts +55 -0
  211. package/src/lib/server/insightsUsage.ts +63 -0
  212. package/src/lib/server/listReleases.ts +109 -44
  213. package/src/lib/server/releaseReachability.ts +8 -7
  214. package/src/lib/server/runtime.server.ts +120 -31
  215. package/src/lib/server/updateFailures.ts +31 -0
  216. package/src/routeTree.gen.ts +44 -44
  217. package/src/router.tsx +3 -2
  218. package/src/routes/-installations-search.ts +32 -8
  219. package/src/routes/-releases-search.ts +76 -29
  220. package/src/routes/__root.tsx +10 -4
  221. package/src/routes/api/bundles/$bundleId/download.ts +2 -5
  222. package/src/routes/api-keys.tsx +5 -2
  223. package/src/routes/index.tsx +167 -104
  224. package/src/routes/insights.tsx +100 -59
  225. package/src/routes/insights_.distribution.tsx +398 -0
  226. package/src/routes/installations.tsx +98 -41
  227. package/src/vite-internal.ts +15 -3
  228. package/src/vite.ts +2 -0
  229. package/.output/public/assets/HashValueDisplay-CB0Eskit.js +0 -1
  230. package/.output/public/assets/InsightsPageHeader-Car5LNiZ.js +0 -1
  231. package/.output/public/assets/api-keys-BzKocqRy.js +0 -1
  232. package/.output/public/assets/api-keys-api-BHcODB7q.js +0 -1
  233. package/.output/public/assets/card-Dhr_eFYj.js +0 -1
  234. package/.output/public/assets/chart-no-axes-combined-Dy4WJv2U.js +0 -1
  235. package/.output/public/assets/composite-Bp98A0Ld.js +0 -1
  236. package/.output/public/assets/createServerFn-CA8fs7QD.js +0 -3
  237. package/.output/public/assets/dialog-CUTrcPlB.js +0 -1
  238. package/.output/public/assets/dist-C_NydL0e.js +0 -1
  239. package/.output/public/assets/index-DdAz-CXv.js +0 -10
  240. package/.output/public/assets/input-group-cSOG4wh_.js +0 -1
  241. package/.output/public/assets/insights-C0PBSZ-n.js +0 -1
  242. package/.output/public/assets/installations-CE33wgbY.js +0 -2
  243. package/.output/public/assets/installations-CStZja8x.js +0 -1
  244. package/.output/public/assets/lazyRouteComponent-Ccp3bwBY.js +0 -1
  245. package/.output/public/assets/link-CI8idAUi.js +0 -1
  246. package/.output/public/assets/loader-circle-BoxLrsOu.js +0 -1
  247. package/.output/public/assets/preload-helper-CQ36nxok.js +0 -1
  248. package/.output/public/assets/refresh-cw-Bqc72UZG.js +0 -1
  249. package/.output/public/assets/routes-DGVXdzpw.js +0 -2
  250. package/.output/public/assets/routes-DTlwOr8I.js +0 -1
  251. package/.output/public/assets/shield-check-uK3MHWJZ.js +0 -1
  252. package/.output/public/assets/signing-CMf4aqDO.js +0 -1
  253. package/.output/public/assets/styles-BCvbtKsm.css +0 -2
  254. package/.output/public/assets/table-2vcV89QB.js +0 -1
  255. package/.output/public/assets/useCompositeListItem-CHLITE_4.js +0 -1
  256. package/.output/public/assets/x-DCd0j8c6.js +0 -1
  257. package/.output/server/_ssr/InsightsPageHeader-Df4Brj8u.mjs +0 -484
  258. package/.output/server/_ssr/api-keys-api-BUPQVSpk.mjs +0 -60
  259. package/.output/server/_ssr/api-keys-rpc-Cs7tS5_j.mjs +0 -136
  260. package/.output/server/_ssr/api-rpc-tAupfGQm.mjs +0 -1399
  261. package/.output/server/_ssr/auth.server-DW71WzsD.mjs +0 -47
  262. package/.output/server/_ssr/bundle-signing-rpc-BhnBw0-d.mjs +0 -16
  263. package/.output/server/_ssr/bundle-signing.server-C4NW5mWx.mjs +0 -12
  264. package/.output/server/_ssr/card-BRiPmi0C.mjs +0 -108
  265. package/.output/server/_ssr/config-Dv8qLDZ0.mjs +0 -13
  266. package/.output/server/_ssr/config.server-afDuAwaG.mjs +0 -368
  267. package/.output/server/_ssr/databaseRows-5bCRTxm-.mjs +0 -126
  268. package/.output/server/_ssr/deleteBundle-BTGwBgzx.mjs +0 -66
  269. package/.output/server/_ssr/getBundleChildren-C0vh4ZvE.mjs +0 -50
  270. package/.output/server/_ssr/insights-BdS364Xu.mjs +0 -460
  271. package/.output/server/_ssr/insightsContract-fjJDBeEE.mjs +0 -303
  272. package/.output/server/_ssr/installations-CtA59MQG.mjs +0 -29
  273. package/.output/server/_ssr/routes-CKrrS2q2.mjs +0 -37
  274. package/.output/server/_ssr/runtime.server-DacU1TBV.mjs +0 -438
  275. package/.output/server/_ssr/server-D_C2rMzf.mjs +0 -7468
  276. package/.output/server/_ssr/signing-Dz1WkZOf.mjs +0 -133
  277. package/.output/server/_ssr/start-DpViQGnt.mjs +0 -4
  278. package/.output/server/_tanstack-start-manifest_v-2MjTyxil.mjs +0 -97
  279. package/src/components/features/insights/InsightsBundleReports.tsx +0 -51
  280. package/src/components/features/signing/BundleSigningPage.tsx +0 -139
  281. package/src/lib/bundle-signing-api.ts +0 -14
  282. package/src/lib/bundle-signing-rpc.ts +0 -16
  283. package/src/lib/server/bundle-signing.server.ts +0 -23
  284. package/src/lib/server/deleteBundle.ts +0 -145
  285. package/src/routes/signing.tsx +0 -37
@@ -1,22 +1,23 @@
1
- import { r as __toESM } from "../_runtime.mjs";
2
- import { c as createServerFn } from "./createServerFn-B2hcXoPM.mjs";
3
- import { A as DialogDescription, D as DialogTitle, J as require_react, M as DialogBackdrop, O as DialogPortal, _ as SelectPortal, a as SliderTrack, b as SelectTrigger$1, c as SelectGroup$1, d as SelectItemText, f as SelectItemIndicator, g as SelectPositioner, h as SelectPopup, i as SliderThumb, j as DialogClose, k as DialogPopup, l as SelectScrollUpArrow, m as SelectList, n as SwitchRoot, o as SliderControl, p as SelectItem$1, q as require_jsx_runtime, r as SliderIndicator, s as SliderRoot, t as SwitchThumb, u as SelectScrollDownArrow, v as SelectIcon, w as DialogRoot, x as SelectRoot, y as SelectValue$1 } from "../_libs/@base-ui/react+[...].mjs";
4
- import { A as ChevronUp, C as Funnel, E as Download, L as ArrowRight, M as ChevronLeft, N as ChevronDown, O as CircleOff, P as Check, T as ExternalLink, a as Tag, b as List, f as Plus, i as Tags, j as ChevronRight, m as Package, n as TriangleAlert, r as Trash2, t as X, u as RotateCcw, v as Minus, w as FingerprintPattern, y as LoaderCircle } from "../_libs/lucide-react.mjs";
5
- import { C as cn, S as buttonVariants, T as useIsMobile, _ as Skeleton, g as SidebarTrigger, n as Input, r as Separator$1, t as Button$1, w as createSsrRpc } from "./createSsrRpc-DjWNJ0uc.mjs";
6
- import { m as Link } from "../_libs/@tanstack/react-router+[...].mjs";
7
- import { i as useQueryClient, n as useQuery, t as useMutation } from "../_libs/tanstack__react-query.mjs";
8
- import { a as Badge, c as CardDescription, d as CardTitle, i as AlertTitle, o as Card, r as AlertDescription, s as CardContent, t as Alert, u as CardHeader } from "./card-BRiPmi0C.mjs";
9
- import { _ as DialogTrigger, a as AlertDialogDescription, d as Dialog$1, f as DialogContent, g as DialogTitle$1, h as DialogHeader, i as AlertDialogContent, l as AlertDialogTitle, m as DialogFooter, n as AlertDialogAction, o as AlertDialogFooter, p as DialogDescription$1, r as AlertDialogCancel, s as AlertDialogHeader, t as AlertDialog$1 } from "./dialog-DS-nw-pA.mjs";
10
- import { a as FieldLabel, c as TableBody, d as TableHeader, f as TableRow, i as FieldGroup, l as TableCell, n as FieldDescription, o as Label, r as FieldError, s as Table, t as Field, u as TableHead } from "./table-CnZmon_Z.mjs";
1
+ import { i as __toESM } from "../_runtime.mjs";
2
+ import { a as SliderTrack, i as SliderThumb, mt as require_react, n as SwitchRoot, o as SliderControl, pt as require_jsx_runtime, r as SliderIndicator, s as SliderRoot, t as SwitchThumb } from "../_libs/@base-ui/react+[...].mjs";
3
+ import { C as Funnel, E as Download, F as Check, M as ChevronRight, N as ChevronLeft, O as CircleOff, P as ChevronDown, R as ArrowRight, T as ExternalLink, _ as Minus, a as Tag, b as List, f as Plus, i as Tags, m as Package, n as TriangleAlert, r as Trash2, t as X, u as RotateCcw, w as FingerprintPattern, y as LoaderCircle } from "../_libs/lucide-react.mjs";
4
+ import { A as useIsMobile, D as buttonVariants, O as cn, S as Skeleton, a as SheetContent, c as SheetTitle, i as Sheet, n as Input, o as SheetDescription, r as Separator$1, s as SheetHeader, t as Button$1, x as SidebarTrigger } from "./sidebar-DKbx2ach.mjs";
5
+ import { h as Link } from "../_libs/@tanstack/react-router+[...].mjs";
6
+ import { a as CardHeader, n as CardContent, o as CardTitle, r as CardDescription, t as Card } from "./card-CPAEKx0w.mjs";
7
+ import { a as Badge, c as FieldError, d as Label, i as AlertTitle, l as FieldGroup, o as Field, r as AlertDescription, s as FieldDescription, t as Alert, u as FieldLabel } from "./field-QCDBVpXA.mjs";
8
+ import { _ as DialogTrigger, a as AlertDialogDescription, d as Dialog$1, f as DialogContent, g as DialogTitle, h as DialogHeader, i as AlertDialogContent, l as AlertDialogTitle, m as DialogFooter, n as AlertDialogAction, o as AlertDialogFooter, p as DialogDescription, r as AlertDialogCancel, s as AlertDialogHeader, t as AlertDialog$1 } from "./dialog-q__BJ7mQ.mjs";
9
+ import { a as TableHeader, i as TableHead, n as TableBody, o as TableRow, r as TableCell, t as Table } from "./table-NGWV8B-S.mjs";
11
10
  import { n as toast } from "../_libs/sonner.mjs";
12
- import { C as normalizeCohortValue, S as isValidCohort, f as getNumericCohortRolloutPosition, g as getPatchFileHash, h as getPatchBaseFileHash, m as getPatchBaseBundleId, r as NUMERIC_COHORT_SIZE, t as INVALID_COHORT_ERROR_MESSAGE, w as normalizeRolloutCohortCount } from "./dist-CyzPaI5v.mjs";
13
- import { r as extractTimestampFromUUIDv7, t as createUUIDv7 } from "./uuidv7-D0QFkPL_.mjs";
14
- import { t as HashValueDisplay } from "./HashValueDisplay-DwpGLfrl.mjs";
15
- import { a as InputGroupText, i as InputGroupInput, n as InputGroupAddon, o as Textarea, t as InputGroup } from "./input-group-BpsnmvZw.mjs";
16
- import { n as updateReleaseFilters, t as Route } from "./routes-CKrrS2q2.mjs";
17
- import { n as require_dayjs_min, t as require_relativeTime } from "../_libs/dayjs.mjs";
11
+ import { E as normalizeRolloutCohortCount, T as normalizeCohortValue, _ as getPatchBaseBundleId, h as getNumericCohortRolloutPosition, i as NUMERIC_COHORT_SIZE, t as INVALID_COHORT_ERROR_MESSAGE, v as getPatchBaseFileHash, w as isValidCohort, y as getPatchFileHash } from "./dist-Cxo9ghYv.mjs";
12
+ import { r as extractTimestampFromUUIDv7 } from "./uuidv7-C8bwiZr8.mjs";
18
13
  import { t as normalizeRange } from "../_libs/verkit.mjs";
19
- //#region node_modules/.nitro/vite/services/ssr/assets/routes-D7Yh_jfj.js
14
+ import { a as useConfigQuery, c as useDeleteReleaseMutation, d as useReleaseCatalogDiagnosticsQuery, f as useReleaseQuery, i as useChannelsQuery, l as usePreflightReleaseMutation, m as useUpdateReleaseMutation, n as useBundleChildrenQuery, o as useCreateChannelMutation, p as useReleasesQuery, r as useBundleQuery, s as useDeleteChannelMutation, t as useBundleChildCountsQuery, u as usePromoteReleaseMutation } from "./api-BEiVs0H7.mjs";
15
+ import { a as SelectItem, i as SelectGroup, n as Select$1, o as SelectTrigger, r as SelectContent, s as SelectValue, t as PlatformIcon } from "./select-CUlInmjk.mjs";
16
+ import { a as InputGroupText, i as InputGroupInput, n as InputGroupAddon, o as Textarea, t as InputGroup } from "./input-group-hCk2nUoU.mjs";
17
+ import { t as HashValueDisplay } from "./HashValueDisplay-GQvFkXoi.mjs";
18
+ import { a as updateReleaseFilters, i as releaseFilterOf, n as Route, r as hasReleaseFilters, s as useReleaseColumns, t as ReleaseSections } from "./routes-Q3Uhmwwz.mjs";
19
+ import { n as require_dayjs_min, t as require_relativeTime } from "../_libs/dayjs.mjs";
20
+ //#region node_modules/.nitro/vite/services/ssr/assets/routes-C6LstNp8.js
20
21
  var import_react = /* @__PURE__ */ __toESM(require_react());
21
22
  var import_jsx_runtime = require_jsx_runtime();
22
23
  var import_dayjs_min = /* @__PURE__ */ __toESM(require_dayjs_min());
@@ -256,175 +257,6 @@ function BundleChildrenPanel({ panelId, bundle, bundles, loading, onDetailClick
256
257
  })
257
258
  });
258
259
  }
259
- var getReleases = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("206547cb1526f961070a989818ca7b9e34f6b2b0e4ab851698c3807fe9fb5e0c"));
260
- var getRelease = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("a6f23116eeaf76166d405e28a95213123025613c6603030894e519015bf48032"));
261
- var updateRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("7ea0186f19f9f2bc2ca4b26e3c59636891cf046957f84287b6783f8d88bd8cb7"));
262
- var preflightRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("b46c95dba95a6a3e8fa5c9d100e3622fa5ae7af4f38e10fb1ed2fa48289a3a8f"));
263
- var deleteRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("d5b58722ce514e3b63a377f736b4823c2011782495442ae4870ed547e392c70b"));
264
- var promoteRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("956539a300d79a7efa191c1cc2d529d62fc4bfd940442548fdbc1404e0d53078"));
265
- var getReleaseCatalogDiagnostics = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("e8c24b7247936f045a145ffd5c177fd0e3df3b52769d67dfbd8d1de491d66396"));
266
- var getConfig = createServerFn().handler(createSsrRpc("51a34c05479a893c7d320bd4cd1604427289d667698c48b9f30a01aabf8a5e68"));
267
- var getChannels = createServerFn().handler(createSsrRpc("79ada05964de8f2123bfcd62b10097d59bf8fd689ef5c7161031e5871d8396c5"));
268
- var createChannel = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("2b9b8d1f49f79a511589617d8d4bfc6094a3acf5264f33651b9569ba66d3f321"));
269
- var deleteChannel = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("52756dde414919a906bfe83d1ab6d29910c63bcafdb47653d6f1df562d958920"));
270
- createServerFn().handler(createSsrRpc("f8bdca3d0579adb812d6404f55d9261a89cdb025e920b1fcad82883646a5fe9e"));
271
- createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("00ccacb4a0212c83ec29f4d11719046ad91ea8291cfc557d514dbf00d3bd7f5f"));
272
- var getBundle = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("1bd85c2a50e24785cb6abb023a247a9f048f37ddfa85cbb1c57e579563bad013"));
273
- var getBundleChildren = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("4370f1bf70b91f1168d85379d3008449a1bedb915e9878ca4ef89d5f3a80fa7f"));
274
- var getBundleChildCounts = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("4ca367070b00f58179a572f0bb8196a4ccdd3881e9b1dbfe33deee0cb6e1f549"));
275
- createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("16cc7c2f080ea5b73e0c6bba815b110dbd7727796036d248ba0d8ae819ddef08"));
276
- createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("3a27ff5679228b86a346b3fe42142e7a5bf0264f73173c0dbe5f07fb37c43cf7"));
277
- createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("61de3b69779c5ce2a5f5d3c27e2cfaca8fba8f14c8803559b9cd733c456494fa"));
278
- var bundleListQueryKey = ["bundles"];
279
- var releaseListQueryKey = ["releases"];
280
- var queryKeys = {
281
- config: ["config"],
282
- channels: ["channels"],
283
- configLoaded: ["config-loaded"],
284
- bundles: {
285
- all: bundleListQueryKey,
286
- list: (filters) => [...bundleListQueryKey, filters ?? {}]
287
- },
288
- releases: {
289
- all: releaseListQueryKey,
290
- list: (filters) => [...releaseListQueryKey, filters ?? {}]
291
- },
292
- release: (releaseId) => ["release", releaseId],
293
- releaseCatalog: (scopeKey) => ["release-catalog", scopeKey],
294
- bundleChildren: {
295
- all: ["bundle-children"],
296
- list: (baseBundleId) => ["bundle-children", baseBundleId],
297
- counts: (bundleIds) => [
298
- "bundle-children",
299
- "counts",
300
- ...bundleIds
301
- ]
302
- },
303
- bundle: (bundleId) => ["bundle", bundleId]
304
- };
305
- function useConfigQuery() {
306
- return useQuery({
307
- queryKey: queryKeys.config,
308
- queryFn: () => getConfig(),
309
- staleTime: Infinity
310
- });
311
- }
312
- function useChannelsQuery() {
313
- return useQuery({
314
- queryKey: queryKeys.channels,
315
- queryFn: () => getChannels(),
316
- staleTime: Infinity
317
- });
318
- }
319
- function useReleasesQuery(filters) {
320
- return useQuery({
321
- queryKey: queryKeys.releases.list(filters),
322
- queryFn: () => getReleases({ data: filters }),
323
- placeholderData: (previousData) => previousData
324
- });
325
- }
326
- function useReleaseQuery(releaseId) {
327
- return useQuery({
328
- enabled: releaseId.length > 0,
329
- queryFn: () => getRelease({ data: { releaseId } }),
330
- queryKey: queryKeys.release(releaseId)
331
- });
332
- }
333
- function useReleaseCatalogDiagnosticsQuery(scopeKey) {
334
- return useQuery({
335
- enabled: scopeKey.length > 0,
336
- queryFn: () => getReleaseCatalogDiagnostics({ data: { scopeKey } }),
337
- queryKey: queryKeys.releaseCatalog(scopeKey)
338
- });
339
- }
340
- function useBundleQuery(bundleId) {
341
- return useQuery({
342
- queryKey: queryKeys.bundle(bundleId),
343
- queryFn: () => getBundle({ data: { bundleId } }),
344
- staleTime: Infinity,
345
- enabled: !!bundleId
346
- });
347
- }
348
- function useBundleChildrenQuery(baseBundleId) {
349
- return useQuery({
350
- queryKey: queryKeys.bundleChildren.list(baseBundleId),
351
- queryFn: () => getBundleChildren({ data: { baseBundleId } }),
352
- staleTime: Infinity,
353
- enabled: !!baseBundleId
354
- });
355
- }
356
- function useBundleChildCountsQuery(bundleIds) {
357
- const normalizedBundleIds = [...bundleIds].sort((left, right) => left.localeCompare(right));
358
- return useQuery({
359
- queryKey: queryKeys.bundleChildren.counts(normalizedBundleIds),
360
- queryFn: () => getBundleChildCounts({ data: { bundleIds: normalizedBundleIds } }),
361
- staleTime: Infinity,
362
- enabled: normalizedBundleIds.length > 0
363
- });
364
- }
365
- function useCreateChannelMutation() {
366
- const queryClient = useQueryClient();
367
- return useMutation({
368
- mutationFn: (input) => createChannel({ data: input }).then((response) => response.data),
369
- onSuccess: async () => {
370
- await queryClient.invalidateQueries({ queryKey: queryKeys.channels });
371
- }
372
- });
373
- }
374
- function useDeleteChannelMutation() {
375
- const queryClient = useQueryClient();
376
- return useMutation({
377
- mutationFn: (input) => deleteChannel({ data: input }).then((response) => response.data),
378
- onSettled: async () => {
379
- await queryClient.invalidateQueries({ queryKey: queryKeys.channels });
380
- }
381
- });
382
- }
383
- function useUpdateReleaseMutation() {
384
- const queryClient = useQueryClient();
385
- return useMutation({
386
- mutationFn: (input) => updateRelease({ data: input }),
387
- onSuccess: async (_, input) => {
388
- await Promise.all([
389
- queryClient.invalidateQueries({ queryKey: queryKeys.releases.all }),
390
- queryClient.invalidateQueries({ queryKey: queryKeys.release(input.releaseId) }),
391
- queryClient.invalidateQueries({ queryKey: ["release-catalog"] }),
392
- queryClient.invalidateQueries({ queryKey: queryKeys.channels })
393
- ]);
394
- }
395
- });
396
- }
397
- function usePreflightReleaseMutation() {
398
- return useMutation({ mutationFn: (input) => preflightRelease({ data: input }) });
399
- }
400
- function useDeleteReleaseMutation() {
401
- const queryClient = useQueryClient();
402
- return useMutation({
403
- mutationFn: (input) => deleteRelease({ data: input }),
404
- onSuccess: async (_, input) => {
405
- queryClient.removeQueries({ queryKey: queryKeys.release(input.releaseId) });
406
- await Promise.all([
407
- queryClient.invalidateQueries({ queryKey: queryKeys.releases.all }),
408
- queryClient.invalidateQueries({ queryKey: ["release-catalog"] }),
409
- queryClient.invalidateQueries({ queryKey: queryKeys.channels })
410
- ]);
411
- }
412
- });
413
- }
414
- function usePromoteReleaseMutation() {
415
- const queryClient = useQueryClient();
416
- return useMutation({
417
- mutationFn: (input) => promoteRelease({ data: input }),
418
- onSuccess: async () => {
419
- await Promise.all([
420
- queryClient.invalidateQueries({ queryKey: queryKeys.releases.all }),
421
- queryClient.invalidateQueries({ queryKey: ["release"] }),
422
- queryClient.invalidateQueries({ queryKey: ["release-catalog"] }),
423
- queryClient.invalidateQueries({ queryKey: queryKeys.channels })
424
- ]);
425
- }
426
- });
427
- }
428
260
  function ChannelManagementDialog({ open, onOpenChange }) {
429
261
  const [channelName, setChannelName] = (0, import_react.useState)("");
430
262
  const [channelToDelete, setChannelToDelete] = (0, import_react.useState)(null);
@@ -436,13 +268,7 @@ function ChannelManagementDialog({ open, onOpenChange }) {
436
268
  event.preventDefault();
437
269
  if (!normalizedName || createChannel.isPending) return;
438
270
  try {
439
- const result = await createChannel.mutateAsync({
440
- row: {
441
- id: createUUIDv7(),
442
- name: normalizedName
443
- },
444
- onConflict: "returnExisting"
445
- });
271
+ const result = await createChannel.mutateAsync({ name: normalizedName });
446
272
  setChannelName("");
447
273
  if (result.inserted) toast.success(`Channel ${result.row.name} created`);
448
274
  else toast.info(`Channel ${result.row.name} already exists`);
@@ -470,10 +296,10 @@ function ChannelManagementDialog({ open, onOpenChange }) {
470
296
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
471
297
  className: "sm:max-w-lg",
472
298
  children: [
473
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogTitle$1, {
299
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogTitle, {
474
300
  className: "flex items-center gap-2",
475
301
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { className: "size-4 text-muted-foreground" }), "Channels"]
476
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription$1, { children: "Create deployment channels and remove them when no bundle uses them. Empty channels remain available until you delete them." })] }),
302
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, { children: "Create deployment channels and remove them when no bundle uses them. Empty channels remain available until you delete them." })] }),
477
303
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", {
478
304
  onSubmit: handleCreate,
479
305
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldGroup, {
@@ -608,7 +434,7 @@ function BundleMetadata({ bundle, release }) {
608
434
  const hbcPatchBaseFileHash = bundle ? getPatchBaseFileHash(bundle) : null;
609
435
  const gitCommitUrl = bundle?.gitCommitHash && isFetched ? getCommitUrl(configData?.console.gitUrl, bundle.gitCommitHash) : null;
610
436
  const target = release.strategy === "APP_VERSION" ? release.target_app_version : release.fingerprint_hash;
611
- if (!(target || bundle?.gitCommitHash || bundle?.fileHash || hbcPatchBaseFileHash || hbcPatchFileHash)) return null;
437
+ if (!(target || bundle?.gitCommitHash || bundle?.manifestFileHash || hbcPatchBaseFileHash || hbcPatchFileHash)) return null;
612
438
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, {
613
439
  className: "p-4 pb-3",
614
440
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
@@ -646,11 +472,11 @@ function BundleMetadata({ bundle, release }) {
646
472
  }) : null]
647
473
  })
648
474
  }) : null,
649
- bundle?.fileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
650
- label: "Bundle hash",
475
+ bundle?.manifestFileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
476
+ label: "Manifest hash",
651
477
  value: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
652
478
  maxLength: 16,
653
- value: bundle.fileHash
479
+ value: bundle.manifestFileHash
654
480
  })
655
481
  }) : null,
656
482
  hbcPatchBaseFileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
@@ -764,7 +590,7 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
764
590
  children: [
765
591
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, {
766
592
  className: "shrink-0 border-b border-border/70 px-4 py-4",
767
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle$1, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription$1, { children: [
593
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription, { children: [
768
594
  rolloutPercentage,
769
595
  "% includes ",
770
596
  selectedCount,
@@ -785,7 +611,7 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
785
611
  })
786
612
  ]
787
613
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
788
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle$1, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription$1, { children: [
614
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription, { children: [
789
615
  rolloutPercentage,
790
616
  "% includes ",
791
617
  selectedCount,
@@ -800,165 +626,6 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
800
626
  ] })
801
627
  })] });
802
628
  }
803
- function AppleIcon({ className }) {
804
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
805
- "aria-hidden": "true",
806
- viewBox: "0 0 24 24",
807
- xmlns: "http://www.w3.org/2000/svg",
808
- className,
809
- fill: "currentColor",
810
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701" })
811
- });
812
- }
813
- function AndroidIcon({ className }) {
814
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
815
- "aria-hidden": "true",
816
- viewBox: "0 0 24 24",
817
- xmlns: "http://www.w3.org/2000/svg",
818
- className,
819
- fill: "currentColor",
820
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18.4395 5.5586c-.675 1.1664-1.352 2.3318-2.0274 3.498-.0366-.0155-.0742-.0286-.1113-.043-1.8249-.6957-3.484-.8-4.42-.787-1.8551.0185-3.3544.4643-4.2597.8203-.084-.1494-1.7526-3.021-2.0215-3.4864a1.1451 1.1451 0 0 0-.1406-.1914c-.3312-.364-.9054-.4859-1.379-.203-.475.282-.7136.9361-.3886 1.5019 1.9466 3.3696-.0966-.2158 1.9473 3.3593.0172.031-.4946.2642-1.3926 1.0177C2.8987 12.176.452 14.772 0 18.9902h24c-.119-1.1108-.3686-2.099-.7461-3.0683-.7438-1.9118-1.8435-3.2928-2.7402-4.1836a12.1048 12.1048 0 0 0-2.1309-1.6875c.6594-1.122 1.312-2.2559 1.9649-3.3848.2077-.3615.1886-.7956-.0079-1.1191a1.1001 1.1001 0 0 0-.8515-.5332c-.5225-.0536-.9392.3128-1.0488.5449zm-.0391 8.461c.3944.5926.324 1.3306-.1563 1.6503-.4799.3197-1.188.0985-1.582-.4941-.3944-.5927-.324-1.3307.1563-1.6504.4727-.315 1.1812-.1086 1.582.4941zM7.207 13.5273c.4803.3197.5506 1.0577.1563 1.6504-.394.5926-1.1038.8138-1.584.4941-.48-.3197-.5503-1.0577-.1563-1.6504.4008-.6021 1.1087-.8106 1.584-.4941z" })
821
- });
822
- }
823
- function PlatformIcon({ platform, className }) {
824
- if (platform === "ios") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppleIcon, { className });
825
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AndroidIcon, { className });
826
- }
827
- var Select$1 = SelectRoot;
828
- function SelectGroup({ className, ...props }) {
829
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectGroup$1, {
830
- "data-slot": "select-group",
831
- className: cn("scroll-my-1 p-1", className),
832
- ...props
833
- });
834
- }
835
- function SelectValue({ className, ...props }) {
836
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue$1, {
837
- "data-slot": "select-value",
838
- className: cn("flex flex-1 text-left", className),
839
- ...props
840
- });
841
- }
842
- function SelectTrigger({ className, size = "default", children, ...props }) {
843
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectTrigger$1, {
844
- "data-slot": "select-trigger",
845
- "data-size": size,
846
- className: cn("flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-input/20 px-2 py-1.5 text-xs/relaxed whitespace-nowrap transition-colors outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-7 data-[size=sm]:h-6 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", className),
847
- ...props,
848
- children: [children, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectIcon, { render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: "pointer-events-none size-3.5 text-muted-foreground" }) })]
849
- });
850
- }
851
- function SelectContent({ className, children, side = "bottom", sideOffset = 4, align = "center", alignOffset = 0, alignItemWithTrigger = true, ...props }) {
852
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectPositioner, {
853
- side,
854
- sideOffset,
855
- align,
856
- alignOffset,
857
- alignItemWithTrigger,
858
- className: "isolate z-50",
859
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectPopup, {
860
- "data-slot": "select-content",
861
- "data-align-trigger": alignItemWithTrigger,
862
- className: cn("dark relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
863
- ...props,
864
- children: [
865
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollUpButton, {}),
866
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectList, { children }),
867
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollDownButton, {})
868
- ]
869
- })
870
- }) });
871
- }
872
- function SelectItem({ className, children, ...props }) {
873
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectItem$1, {
874
- "data-slot": "select-item",
875
- className: cn("relative flex min-h-7 w-full cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className),
876
- ...props,
877
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItemText, {
878
- className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap",
879
- children
880
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItemIndicator, {
881
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "pointer-events-none absolute right-2 flex items-center justify-center" }),
882
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "pointer-events-none" })
883
- })]
884
- });
885
- }
886
- function SelectScrollUpButton({ className, ...props }) {
887
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollUpArrow, {
888
- "data-slot": "select-scroll-up-button",
889
- className: cn("top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5", className),
890
- ...props,
891
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronUp, {})
892
- });
893
- }
894
- function SelectScrollDownButton({ className, ...props }) {
895
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollDownArrow, {
896
- "data-slot": "select-scroll-down-button",
897
- className: cn("bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5", className),
898
- ...props,
899
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {})
900
- });
901
- }
902
- function Sheet({ ...props }) {
903
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogRoot, {
904
- "data-slot": "sheet",
905
- ...props
906
- });
907
- }
908
- function SheetPortal({ ...props }) {
909
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogPortal, {
910
- "data-slot": "sheet-portal",
911
- ...props
912
- });
913
- }
914
- function SheetOverlay({ className, ...props }) {
915
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogBackdrop, {
916
- "data-slot": "sheet-overlay",
917
- className: cn("fixed inset-0 z-50 bg-black/80 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs", className),
918
- ...props
919
- });
920
- }
921
- function SheetContent({ className, children, side = "right", showCloseButton = true, ...props }) {
922
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SheetPortal, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SheetOverlay, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogPopup, {
923
- "data-slot": "sheet-content",
924
- "data-side": side,
925
- className: cn("fixed z-50 flex flex-col bg-background bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm", className),
926
- ...props,
927
- children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose, {
928
- "data-slot": "sheet-close",
929
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
930
- variant: "ghost",
931
- className: "absolute top-4 right-4",
932
- size: "icon-sm"
933
- }),
934
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
935
- className: "sr-only",
936
- children: "Close"
937
- })]
938
- })]
939
- })] });
940
- }
941
- function SheetHeader({ className, ...props }) {
942
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
943
- "data-slot": "sheet-header",
944
- className: cn("flex flex-col gap-1.5 p-6", className),
945
- ...props
946
- });
947
- }
948
- function SheetTitle({ className, ...props }) {
949
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, {
950
- "data-slot": "sheet-title",
951
- className: cn("text-sm font-medium text-foreground", className),
952
- ...props
953
- });
954
- }
955
- function SheetDescription({ className, ...props }) {
956
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, {
957
- "data-slot": "sheet-description",
958
- className: cn("text-xs/relaxed text-muted-foreground", className),
959
- ...props
960
- });
961
- }
962
629
  function Slider$1({ className, defaultValue, value, min = 0, max = 100, ...props }) {
963
630
  const _values = Array.isArray(value) ? value : value !== void 0 ? [value] : Array.isArray(defaultValue) ? defaultValue : defaultValue !== void 0 ? [defaultValue] : [min];
964
631
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SliderRoot, {
@@ -1079,7 +746,7 @@ function RolloutPercentageInput({ value, onChange }) {
1079
746
  })]
1080
747
  });
1081
748
  }
1082
- function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
749
+ function ReleaseEditorSheet({ channels, onOpenChange, onShowScope, open, releaseId }) {
1083
750
  const releaseQuery = useReleaseQuery(releaseId);
1084
751
  const release = releaseQuery.data;
1085
752
  const bundleQuery = useBundleQuery(release?.bundle_id ?? "");
@@ -1258,6 +925,11 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1258
925
  }) : null, release && draft ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1259
926
  className: "flex flex-col gap-6 px-4 pb-4 sm:px-6 sm:pb-6",
1260
927
  children: [
928
+ channelName ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseSections, { release: {
929
+ platform: release.platform,
930
+ channel: channelName,
931
+ releaseId: release.id
932
+ } }) : null,
1261
933
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
1262
934
  "aria-labelledby": "delivery-settings-heading",
1263
935
  className: "flex flex-col gap-4",
@@ -1436,7 +1108,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1436
1108
  },
1437
1109
  size: "sm",
1438
1110
  variant: "outline",
1439
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { "data-icon": "inline-start" }), "Download bundle"]
1111
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { "data-icon": "inline-start" }), "Download manifest"]
1440
1112
  }) : null,
1441
1113
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1442
1114
  className: "w-full",
@@ -1499,10 +1171,20 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1499
1171
  })] }),
1500
1172
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1501
1173
  className: "sm:col-span-2",
1502
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Scope key" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1503
- className: "mt-1 break-all font-mono text-foreground",
1504
- children: release.scope_key
1505
- })]
1174
+ children: [
1175
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Scope key" }),
1176
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1177
+ className: "mt-1 break-all font-mono text-foreground",
1178
+ children: release.scope_key
1179
+ }),
1180
+ onShowScope ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1181
+ className: "mt-1 h-auto px-0 text-xs",
1182
+ onClick: () => onShowScope(release.scope_key),
1183
+ size: "sm",
1184
+ variant: "link",
1185
+ children: "Show bundles for this target"
1186
+ }) : null
1187
+ ]
1506
1188
  })
1507
1189
  ]
1508
1190
  }),
@@ -1561,7 +1243,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1561
1243
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
1562
1244
  showCloseButton: !promote.isPending,
1563
1245
  children: [
1564
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle$1, { children: "Promote to Channel" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription$1, { children: "Choose how to promote this Bundle, then select the target channel." })] }),
1246
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Promote to Channel" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, { children: "Choose how to promote this Bundle, then select the target channel." })] }),
1565
1247
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1566
1248
  className: "space-y-4 py-4",
1567
1249
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -1667,18 +1349,25 @@ function RolloutPercentageBadge({ percentage, className }) {
1667
1349
  });
1668
1350
  }
1669
1351
  var PAGE_SIZE = 20;
1670
- var platformFilterItems = [
1352
+ var platformFilterItems = [{
1353
+ label: "iOS",
1354
+ value: "ios"
1355
+ }, {
1356
+ label: "Android",
1357
+ value: "android"
1358
+ }];
1359
+ var statusFilterItems = [
1671
1360
  {
1672
- label: "All Platforms",
1361
+ label: "Any Status",
1673
1362
  value: "all"
1674
1363
  },
1675
1364
  {
1676
- label: "iOS",
1677
- value: "ios"
1365
+ label: "Enabled",
1366
+ value: "enabled"
1678
1367
  },
1679
1368
  {
1680
- label: "Android",
1681
- value: "android"
1369
+ label: "Disabled",
1370
+ value: "disabled"
1682
1371
  }
1683
1372
  ];
1684
1373
  var dateFormatter = new Intl.DateTimeFormat(void 0, {
@@ -1687,8 +1376,8 @@ var dateFormatter = new Intl.DateTimeFormat(void 0, {
1687
1376
  });
1688
1377
  var tableDateFormatter = new Intl.DateTimeFormat(void 0, { dateStyle: "medium" });
1689
1378
  function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, search }) {
1690
- const [targetAppVersion, setTargetAppVersion] = (0, import_react.useState)(search.targetAppVersion ?? "");
1691
- const hasFilters = Boolean(search.bundleId || search.channelId || search.enabled !== void 0 || search.platform || search.targetAppVersion);
1379
+ const hasFilters = hasReleaseFilters(search);
1380
+ const channelSelected = search.channelId !== void 0;
1692
1381
  const channelFilterItems = [{
1693
1382
  label: "All Channels",
1694
1383
  value: "all"
@@ -1696,12 +1385,6 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1696
1385
  label: channel.name,
1697
1386
  value: channel.id
1698
1387
  }))];
1699
- const applyTargetAppVersion = () => {
1700
- onChange({ targetAppVersion: targetAppVersion.trim() || void 0 });
1701
- };
1702
- (0, import_react.useEffect)(() => {
1703
- setTargetAppVersion(search.targetAppVersion ?? "");
1704
- }, [search.targetAppVersion]);
1705
1388
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
1706
1389
  className: "sticky top-0 z-10 flex shrink-0 flex-wrap items-center gap-2 border-b bg-background px-3 py-3 sm:h-12 sm:flex-nowrap sm:bg-card/70 sm:px-4 sm:py-0 sm:backdrop-blur-sm",
1707
1390
  children: [
@@ -1717,40 +1400,6 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1717
1400
  children: "Filters"
1718
1401
  })]
1719
1402
  }),
1720
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1721
- items: platformFilterItems,
1722
- onValueChange: (value) => onChange({ platform: value === "all" ? void 0 : value }),
1723
- value: search.platform ?? "all",
1724
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1725
- "aria-label": "Platform",
1726
- className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1727
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1728
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [
1729
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1730
- value: "all",
1731
- children: "All Platforms"
1732
- }),
1733
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1734
- value: "ios",
1735
- children: "iOS"
1736
- }),
1737
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1738
- value: "android",
1739
- children: "Android"
1740
- })
1741
- ] }) })]
1742
- }),
1743
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, {
1744
- "aria-label": "Target app version",
1745
- className: "h-8 w-full min-w-[132px] text-xs sm:w-[160px]",
1746
- onBlur: applyTargetAppVersion,
1747
- onChange: (event) => setTargetAppVersion(event.target.value),
1748
- onKeyDown: (event) => {
1749
- if (event.key === "Enter") applyTargetAppVersion();
1750
- },
1751
- placeholder: "Target version",
1752
- value: targetAppVersion
1753
- }),
1754
1403
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1755
1404
  items: channelFilterItems,
1756
1405
  onValueChange: (value) => onChange({ channelId: value === null || value === "all" ? void 0 : value }),
@@ -1767,6 +1416,48 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1767
1416
  children: channel.name
1768
1417
  }, channel.id))] }) })]
1769
1418
  }),
1419
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1420
+ disabled: !channelSelected,
1421
+ items: platformFilterItems,
1422
+ onValueChange: (value) => onChange({ platform: value === "android" ? "android" : "ios" }),
1423
+ value: search.platform ?? "ios",
1424
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1425
+ "aria-label": "Platform",
1426
+ className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1427
+ title: channelSelected ? void 0 : "Choose a channel first",
1428
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1429
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1430
+ value: "ios",
1431
+ children: "iOS"
1432
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1433
+ value: "android",
1434
+ children: "Android"
1435
+ })] }) })]
1436
+ }),
1437
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1438
+ disabled: !channelSelected && search.scopeKey === void 0,
1439
+ items: statusFilterItems,
1440
+ onValueChange: (value) => onChange({ enabled: value === "enabled" ? true : value === "disabled" ? false : void 0 }),
1441
+ value: search.enabled === void 0 ? "all" : search.enabled ? "enabled" : "disabled",
1442
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1443
+ "aria-label": "Status",
1444
+ className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1445
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1446
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [
1447
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1448
+ value: "all",
1449
+ children: "Any Status"
1450
+ }),
1451
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1452
+ value: "enabled",
1453
+ children: "Enabled"
1454
+ }),
1455
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1456
+ value: "disabled",
1457
+ children: "Disabled"
1458
+ })
1459
+ ] }) })]
1460
+ }),
1770
1461
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1771
1462
  "aria-label": "Manage channels",
1772
1463
  onClick: onManageChannels,
@@ -1786,6 +1477,17 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1786
1477
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3" })
1787
1478
  })]
1788
1479
  }) : null,
1480
+ search.scopeKey ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge, {
1481
+ className: "max-w-48 gap-1",
1482
+ variant: "secondary",
1483
+ children: ["Target filter", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
1484
+ "aria-label": "Clear target filter",
1485
+ className: "rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1486
+ onClick: () => onChange({ scopeKey: void 0 }),
1487
+ type: "button",
1488
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3" })
1489
+ })]
1490
+ }) : null,
1789
1491
  hasFilters ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
1790
1492
  className: "h-8 px-2 text-xs text-muted-foreground hover:text-foreground sm:ml-auto",
1791
1493
  onClick: onClear,
@@ -1883,18 +1585,24 @@ function BundlesPage() {
1883
1585
  const releasesQuery = useReleasesQuery({
1884
1586
  afterReleaseId: search.afterReleaseId,
1885
1587
  beforeReleaseId: search.beforeReleaseId,
1886
- bundleId: search.bundleId,
1887
- channelId: search.channelId,
1888
- enabled: search.enabled,
1889
- limit: PAGE_SIZE,
1890
- page: search.page,
1891
- platform: search.platform,
1892
- targetAppVersion: search.targetAppVersion
1588
+ filter: releaseFilterOf(search),
1589
+ limit: PAGE_SIZE
1893
1590
  });
1894
1591
  const channels = useChannelsQuery().data ?? [];
1895
1592
  const releases = releasesQuery.data?.data ?? [];
1896
1593
  const patchCountsByBundleId = useBundleChildCountsQuery(Array.from(new Set(releases.flatMap((release) => release.bundle_id ? [release.bundle_id] : [])))).data ?? {};
1897
- const pagination = releasesQuery.data?.pagination;
1594
+ const nextCursor = releasesQuery.data?.next;
1595
+ const previousCursor = releasesQuery.data?.previous;
1596
+ const slotReleases = releases.flatMap((release) => {
1597
+ const channel = channels.find((item) => item.id === release.channel_id)?.name;
1598
+ return channel ? [{
1599
+ releaseId: release.id,
1600
+ platform: release.platform,
1601
+ channel
1602
+ }] : [];
1603
+ });
1604
+ const featureColumns = useReleaseColumns();
1605
+ const columnCount = 10 + featureColumns.length;
1898
1606
  const channelNames = new Map(channels.map((channel) => [channel.id, channel.name]));
1899
1607
  (0, import_react.useEffect)(() => {
1900
1608
  if (expandedReleaseId && !releases.some((release) => release.id === expandedReleaseId)) setExpandedReleaseId(void 0);
@@ -1917,26 +1625,25 @@ function BundlesPage() {
1917
1625
  }
1918
1626
  changeFilters({ bundleId: bundle.id });
1919
1627
  };
1920
- const currentPage = pagination?.currentPage ?? 1;
1921
- const startEntry = releases.length === 0 ? 0 : (currentPage - 1) * PAGE_SIZE + 1;
1922
- const endEntry = startEntry === 0 ? 0 : startEntry + releases.length - 1;
1923
- const previousPage = currentPage - 1;
1924
- const firstReleaseId = releases[0]?.id;
1925
- const lastReleaseId = releases.at(-1)?.id;
1926
- const previousSearch = pagination?.hasPreviousPage && firstReleaseId ? {
1628
+ const onLaterPage = search.afterReleaseId !== void 0 || search.beforeReleaseId !== void 0;
1629
+ const previousSearch = previousCursor ? {
1927
1630
  ...search,
1928
- afterReleaseId: firstReleaseId,
1631
+ afterReleaseId: previousCursor,
1929
1632
  beforeReleaseId: void 0,
1930
- page: previousPage > 1 ? previousPage : void 0,
1931
1633
  releaseId: void 0
1932
1634
  } : null;
1933
- const nextSearch = pagination?.hasNextPage && lastReleaseId ? {
1635
+ const nextSearch = nextCursor ? {
1934
1636
  ...search,
1935
1637
  afterReleaseId: void 0,
1936
- beforeReleaseId: lastReleaseId,
1937
- page: currentPage + 1,
1638
+ beforeReleaseId: nextCursor,
1938
1639
  releaseId: void 0
1939
1640
  } : null;
1641
+ const newestSearch = {
1642
+ ...search,
1643
+ afterReleaseId: void 0,
1644
+ beforeReleaseId: void 0,
1645
+ releaseId: void 0
1646
+ };
1940
1647
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1941
1648
  className: "flex h-svh min-h-0 min-w-0 flex-col",
1942
1649
  children: [
@@ -2030,6 +1737,16 @@ function BundlesPage() {
2030
1737
  children: patchCount === void 0 ? "Checking" : patchCount > 0 ? `${patchCount} ${patchCount === 1 ? "patch" : "patches"}` : "—"
2031
1738
  })]
2032
1739
  }),
1740
+ featureColumns.map(({ Cell, feature, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1741
+ className: "col-span-2 rounded-md bg-muted/40 p-3",
1742
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
1743
+ className: "mb-2 text-muted-foreground",
1744
+ children: label
1745
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cell, {
1746
+ releaseId: release.id,
1747
+ releases: slotReleases
1748
+ }) })]
1749
+ }, feature)),
2033
1750
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2034
1751
  className: "col-span-2 flex flex-wrap items-center gap-2 rounded-md bg-muted/40 p-3",
2035
1752
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseStateBadge, { release }), release.should_force_update ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
@@ -2068,7 +1785,7 @@ function BundlesPage() {
2068
1785
  }) : null] }, release.id);
2069
1786
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
2070
1787
  className: "p-8 text-center text-sm text-muted-foreground",
2071
- children: search.bundleId || search.channelId || search.enabled !== void 0 || search.platform || search.targetAppVersion ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
1788
+ children: onLaterPage ? "No more bundles on this side." : hasReleaseFilters(search) ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
2072
1789
  })
2073
1790
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table, {
2074
1791
  className: "min-w-max",
@@ -2085,12 +1802,13 @@ function BundlesPage() {
2085
1802
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Enabled" }),
2086
1803
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Force update" }),
2087
1804
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Rollout" }),
1805
+ featureColumns.map(({ feature, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: label }, feature)),
2088
1806
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Message" }),
2089
1807
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Created" })
2090
1808
  ]
2091
1809
  })
2092
1810
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableBody, { children: [releasesQuery.isPending ? Array.from({ length: 7 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2093
- colSpan: 10,
1811
+ colSpan: columnCount,
2094
1812
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, { className: "h-8 w-full" })
2095
1813
  }) }, index)) : releases.map((release) => {
2096
1814
  const isExpanded = expandedReleaseId === release.id;
@@ -2184,6 +1902,10 @@ function BundlesPage() {
2184
1902
  })]
2185
1903
  }) }),
2186
1904
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RolloutPercentageBadge, { percentage: release.rollout_cohort_count / 10 }) }),
1905
+ featureColumns.map(({ Cell, feature }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cell, {
1906
+ releaseId: release.id,
1907
+ releases: slotReleases
1908
+ }) }, feature)),
2187
1909
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2188
1910
  className: "text-sm text-muted-foreground",
2189
1911
  title: release.message ?? void 0,
@@ -2199,7 +1921,7 @@ function BundlesPage() {
2199
1921
  className: "hover:bg-transparent",
2200
1922
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2201
1923
  className: "border-t-0 p-0",
2202
- colSpan: 10,
1924
+ colSpan: columnCount,
2203
1925
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseBundleChildrenPanel, {
2204
1926
  onDetailClick: openChildBundle,
2205
1927
  panelId,
@@ -2209,8 +1931,8 @@ function BundlesPage() {
2209
1931
  }) : null] }, release.id);
2210
1932
  }), !releasesQuery.isPending && releases.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2211
1933
  className: "h-40 text-center text-muted-foreground",
2212
- colSpan: 10,
2213
- children: search.bundleId || search.channelId || search.enabled !== void 0 || search.platform || search.targetAppVersion ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
1934
+ colSpan: columnCount,
1935
+ children: onLaterPage ? "No more bundles on this side." : hasReleaseFilters(search) ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
2214
1936
  }) }) : null] })]
2215
1937
  })
2216
1938
  }), !releasesQuery.isError && !releasesQuery.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("nav", {
@@ -2219,29 +1941,27 @@ function BundlesPage() {
2219
1941
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
2220
1942
  className: "text-xs font-medium text-muted-foreground",
2221
1943
  children: [
2222
- "Showing ",
2223
1944
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2224
1945
  className: "text-foreground",
2225
- children: startEntry
1946
+ children: releases.length
2226
1947
  }),
2227
- " to",
2228
1948
  " ",
2229
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2230
- className: "text-foreground",
2231
- children: endEntry
2232
- }),
2233
- " entries"
1949
+ releases.length === 1 ? "entry" : "entries",
1950
+ ", newest first"
2234
1951
  ]
2235
1952
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2236
1953
  className: "flex flex-wrap items-center gap-3 sm:justify-end",
2237
1954
  children: [
2238
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
2239
- className: "text-xs font-medium text-muted-foreground",
2240
- children: ["Page ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2241
- className: "text-foreground",
2242
- children: currentPage
2243
- })]
2244
- }),
1955
+ onLaterPage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
1956
+ className: buttonVariants({
1957
+ className: "h-8 flex-1 px-3 text-xs sm:flex-none",
1958
+ size: "sm",
1959
+ variant: "ghost"
1960
+ }),
1961
+ search: newestSearch,
1962
+ to: "/",
1963
+ children: "Newest"
1964
+ }) : null,
2245
1965
  previousSearch ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
2246
1966
  className: buttonVariants({
2247
1967
  className: "h-8 flex-1 px-3 text-xs sm:flex-none",
@@ -2284,6 +2004,7 @@ function BundlesPage() {
2284
2004
  ...search,
2285
2005
  releaseId: void 0
2286
2006
  }, false),
2007
+ onShowScope: (scopeKey) => changeFilters({ scopeKey }),
2287
2008
  open: Boolean(search.releaseId),
2288
2009
  releaseId: search.releaseId ?? ""
2289
2010
  }),