@oxy.so/bloom 3.2.0 → 3.3.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 (496) hide show
  1. package/docs/adoption-matrix.mdx +3 -3
  2. package/docs/ai-chat.mdx +31 -3
  3. package/docs/composer-panel.mdx +23 -6
  4. package/lib/commonjs/agent-limits-card/AgentLimitsCard.js +25 -23
  5. package/lib/commonjs/agent-limits-card/AgentLimitsCard.js.map +1 -1
  6. package/lib/commonjs/ai-chat/AiChatContainer.js +122 -14
  7. package/lib/commonjs/ai-chat/AiChatContainer.js.map +1 -1
  8. package/lib/commonjs/ai-chat/AiChatShell.js +46 -6
  9. package/lib/commonjs/ai-chat/AiChatShell.js.map +1 -1
  10. package/lib/commonjs/ai-chat/context.js +5 -1
  11. package/lib/commonjs/ai-chat/context.js.map +1 -1
  12. package/lib/commonjs/ai-chat/index.js +7 -0
  13. package/lib/commonjs/ai-chat/index.js.map +1 -1
  14. package/lib/commonjs/ai-chat/index.web.js +7 -0
  15. package/lib/commonjs/ai-chat/index.web.js.map +1 -1
  16. package/lib/commonjs/app-shell/AppShellHeader.js +5 -4
  17. package/lib/commonjs/app-shell/AppShellHeader.js.map +1 -1
  18. package/lib/commonjs/app-shell/AppShellMenuButton.js +3 -2
  19. package/lib/commonjs/app-shell/AppShellMenuButton.js.map +1 -1
  20. package/lib/commonjs/app-shell/NotificationBell.js +6 -6
  21. package/lib/commonjs/app-shell/NotificationBell.js.map +1 -1
  22. package/lib/commonjs/auth-card/AuthCard.js +20 -20
  23. package/lib/commonjs/auth-card/AuthCard.js.map +1 -1
  24. package/lib/commonjs/calendar/CalendarViewEventDetails.js +27 -22
  25. package/lib/commonjs/calendar/CalendarViewEventDetails.js.map +1 -1
  26. package/lib/commonjs/calendar/CalendarViewHeader.js +6 -5
  27. package/lib/commonjs/calendar/CalendarViewHeader.js.map +1 -1
  28. package/lib/commonjs/calendar/CalendarViewInboxMenu.js +9 -7
  29. package/lib/commonjs/calendar/CalendarViewInboxMenu.js.map +1 -1
  30. package/lib/commonjs/carousel/Carousel.js +4 -3
  31. package/lib/commonjs/carousel/Carousel.js.map +1 -1
  32. package/lib/commonjs/chart-cards/BarListCard.js +10 -10
  33. package/lib/commonjs/chart-cards/BarListCard.js.map +1 -1
  34. package/lib/commonjs/chart-cards/primitives/ChartRangePill.js +10 -8
  35. package/lib/commonjs/chart-cards/primitives/ChartRangePill.js.map +1 -1
  36. package/lib/commonjs/chat-indicators/MessageStatus.js +8 -5
  37. package/lib/commonjs/chat-indicators/MessageStatus.js.map +1 -1
  38. package/lib/commonjs/composer-panel/ComposerControls.js +61 -0
  39. package/lib/commonjs/composer-panel/ComposerControls.js.map +1 -1
  40. package/lib/commonjs/composer-panel/ComposerPanelBase.js +12 -4
  41. package/lib/commonjs/composer-panel/ComposerPanelBase.js.map +1 -1
  42. package/lib/commonjs/composer-panel/ComposerPillBase.js +114 -79
  43. package/lib/commonjs/composer-panel/ComposerPillBase.js.map +1 -1
  44. package/lib/commonjs/composer-panel/EffortSlider.js +24 -15
  45. package/lib/commonjs/composer-panel/EffortSlider.js.map +1 -1
  46. package/lib/commonjs/composer-panel/ModelPickerBase.js +15 -4
  47. package/lib/commonjs/composer-panel/ModelPickerBase.js.map +1 -1
  48. package/lib/commonjs/data-table/DataTableRowActions.js +2 -2
  49. package/lib/commonjs/data-table/DataTableRowActions.js.map +1 -1
  50. package/lib/commonjs/data-table/DataTableSearch.js +8 -8
  51. package/lib/commonjs/data-table/DataTableSearch.js.map +1 -1
  52. package/lib/commonjs/date-picker/MeetingScheduler.js +23 -21
  53. package/lib/commonjs/date-picker/MeetingScheduler.js.map +1 -1
  54. package/lib/commonjs/date-picker/PickerShell.js +2 -2
  55. package/lib/commonjs/date-picker/PickerShell.js.map +1 -1
  56. package/lib/commonjs/dialog/DialogHeader.js +25 -17
  57. package/lib/commonjs/dialog/DialogHeader.js.map +1 -1
  58. package/lib/commonjs/eviction/EvictionReportCard.js +27 -20
  59. package/lib/commonjs/eviction/EvictionReportCard.js.map +1 -1
  60. package/lib/commonjs/eviction/constants.js +16 -9
  61. package/lib/commonjs/eviction/constants.js.map +1 -1
  62. package/lib/commonjs/file-upload/FileUpload.js +14 -11
  63. package/lib/commonjs/file-upload/FileUpload.js.map +1 -1
  64. package/lib/commonjs/floating/menu-rows.js +2 -2
  65. package/lib/commonjs/floating/menu-rows.js.map +1 -1
  66. package/lib/commonjs/floating/menu-sub-flyout.js +2 -2
  67. package/lib/commonjs/floating/menu-sub-flyout.js.map +1 -1
  68. package/lib/commonjs/floating/menu-sub-inline.js +3 -2
  69. package/lib/commonjs/floating/menu-sub-inline.js.map +1 -1
  70. package/lib/commonjs/listing-card/ListingCard.js +29 -28
  71. package/lib/commonjs/listing-card/ListingCard.js.map +1 -1
  72. package/lib/commonjs/listing-details/ContactCard.js +21 -17
  73. package/lib/commonjs/listing-details/ContactCard.js.map +1 -1
  74. package/lib/commonjs/listing-details/FloorPlan.js +5 -5
  75. package/lib/commonjs/listing-details/FloorPlan.js.map +1 -1
  76. package/lib/commonjs/listing-details/ListingPhotoGrid.js +4 -4
  77. package/lib/commonjs/listing-details/ListingPhotoGrid.js.map +1 -1
  78. package/lib/commonjs/listing-details/ReviewCard.js +13 -13
  79. package/lib/commonjs/listing-details/ReviewCard.js.map +1 -1
  80. package/lib/commonjs/listing-details/ReviewSummary.js +7 -7
  81. package/lib/commonjs/listing-details/ReviewSummary.js.map +1 -1
  82. package/lib/commonjs/message-bubble/CallSummaryRow.js +10 -7
  83. package/lib/commonjs/message-bubble/CallSummaryRow.js.map +1 -1
  84. package/lib/commonjs/message-bubble/SwipeToReply.js +2 -2
  85. package/lib/commonjs/message-bubble/SwipeToReply.js.map +1 -1
  86. package/lib/commonjs/message-bubble/parts.js +20 -17
  87. package/lib/commonjs/message-bubble/parts.js.map +1 -1
  88. package/lib/commonjs/notification-center/NotificationCenter.js +24 -20
  89. package/lib/commonjs/notification-center/NotificationCenter.js.map +1 -1
  90. package/lib/commonjs/page-header/PageHeader.js +9 -9
  91. package/lib/commonjs/page-header/PageHeader.js.map +1 -1
  92. package/lib/commonjs/place-reviews/PlaceReviewCard.js +20 -15
  93. package/lib/commonjs/place-reviews/PlaceReviewCard.js.map +1 -1
  94. package/lib/commonjs/place-reviews/PlaceReviewSummary.js +6 -5
  95. package/lib/commonjs/place-reviews/PlaceReviewSummary.js.map +1 -1
  96. package/lib/commonjs/place-reviews/WriteReviewPrompt.js +9 -7
  97. package/lib/commonjs/place-reviews/WriteReviewPrompt.js.map +1 -1
  98. package/lib/commonjs/property-insights/EnergyBadge.js +5 -5
  99. package/lib/commonjs/property-insights/EnergyBadge.js.map +1 -1
  100. package/lib/commonjs/property-insights/EnergyLabel.js +10 -10
  101. package/lib/commonjs/property-insights/EnergyLabel.js.map +1 -1
  102. package/lib/commonjs/property-insights/NearbyPlaces.js +6 -6
  103. package/lib/commonjs/property-insights/NearbyPlaces.js.map +1 -1
  104. package/lib/commonjs/property-insights/PriceEstimate.js +17 -16
  105. package/lib/commonjs/property-insights/PriceEstimate.js.map +1 -1
  106. package/lib/commonjs/property-insights/PriceHistoryChart.js +7 -7
  107. package/lib/commonjs/property-insights/PriceHistoryChart.js.map +1 -1
  108. package/lib/commonjs/property-insights/RentHistoryList.js +7 -7
  109. package/lib/commonjs/property-insights/RentHistoryList.js.map +1 -1
  110. package/lib/commonjs/recent-hires-card/RecentHiresCard.js +10 -9
  111. package/lib/commonjs/recent-hires-card/RecentHiresCard.js.map +1 -1
  112. package/lib/commonjs/select/Select.js +2 -2
  113. package/lib/commonjs/select/Select.js.map +1 -1
  114. package/lib/commonjs/select/Select.web.js +2 -2
  115. package/lib/commonjs/select/Select.web.js.map +1 -1
  116. package/lib/commonjs/select/shared.js +3 -2
  117. package/lib/commonjs/select/shared.js.map +1 -1
  118. package/lib/commonjs/settings-modal/SettingsFields.js +8 -8
  119. package/lib/commonjs/settings-modal/SettingsFields.js.map +1 -1
  120. package/lib/commonjs/settings-modal/SettingsModal.js +17 -14
  121. package/lib/commonjs/settings-modal/SettingsModal.js.map +1 -1
  122. package/lib/commonjs/settings-modal/SettingsStorage.js +30 -22
  123. package/lib/commonjs/settings-modal/SettingsStorage.js.map +1 -1
  124. package/lib/commonjs/settings-modal/SettingsTools.js +18 -17
  125. package/lib/commonjs/settings-modal/SettingsTools.js.map +1 -1
  126. package/lib/commonjs/sidebar/Sidebar.js +19 -17
  127. package/lib/commonjs/sidebar/Sidebar.js.map +1 -1
  128. package/lib/commonjs/sidebar/SidebarFolder.js +7 -6
  129. package/lib/commonjs/sidebar/SidebarFolder.js.map +1 -1
  130. package/lib/commonjs/sidebar/SidebarUserMenu.js +8 -7
  131. package/lib/commonjs/sidebar/SidebarUserMenu.js.map +1 -1
  132. package/lib/commonjs/task-list/TaskList.js +6 -6
  133. package/lib/commonjs/task-list/TaskList.js.map +1 -1
  134. package/lib/commonjs/tenancy/DocumentList.js +10 -8
  135. package/lib/commonjs/tenancy/DocumentList.js.map +1 -1
  136. package/lib/commonjs/tenancy/MaintenanceRequestCard.js +9 -9
  137. package/lib/commonjs/tenancy/MaintenanceRequestCard.js.map +1 -1
  138. package/lib/commonjs/tenancy/RentPaymentList.js +19 -19
  139. package/lib/commonjs/tenancy/RentPaymentList.js.map +1 -1
  140. package/lib/commonjs/tenancy/constants.js +18 -10
  141. package/lib/commonjs/tenancy/constants.js.map +1 -1
  142. package/lib/commonjs/text-field/TextField.js +11 -11
  143. package/lib/commonjs/text-field/TextField.js.map +1 -1
  144. package/lib/commonjs/theme-toggle/ThemeToggle.js +7 -6
  145. package/lib/commonjs/theme-toggle/ThemeToggle.js.map +1 -1
  146. package/lib/commonjs/web-search/WebSearch.js +8 -8
  147. package/lib/commonjs/web-search/WebSearch.js.map +1 -1
  148. package/lib/commonjs/zoomable-media-gallery/ZoomableMediaGallery.js +19 -14
  149. package/lib/commonjs/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -1
  150. package/lib/module/agent-limits-card/AgentLimitsCard.js +3 -1
  151. package/lib/module/agent-limits-card/AgentLimitsCard.js.map +1 -1
  152. package/lib/module/ai-chat/AiChatContainer.js +122 -14
  153. package/lib/module/ai-chat/AiChatContainer.js.map +1 -1
  154. package/lib/module/ai-chat/AiChatShell.js +46 -6
  155. package/lib/module/ai-chat/AiChatShell.js.map +1 -1
  156. package/lib/module/ai-chat/context.js +5 -1
  157. package/lib/module/ai-chat/context.js.map +1 -1
  158. package/lib/module/ai-chat/index.js +1 -0
  159. package/lib/module/ai-chat/index.js.map +1 -1
  160. package/lib/module/ai-chat/index.web.js +1 -0
  161. package/lib/module/ai-chat/index.web.js.map +1 -1
  162. package/lib/module/app-shell/AppShellHeader.js +2 -1
  163. package/lib/module/app-shell/AppShellHeader.js.map +1 -1
  164. package/lib/module/app-shell/AppShellMenuButton.js +2 -1
  165. package/lib/module/app-shell/AppShellMenuButton.js.map +1 -1
  166. package/lib/module/app-shell/NotificationBell.js +1 -1
  167. package/lib/module/app-shell/NotificationBell.js.map +1 -1
  168. package/lib/module/auth-card/AuthCard.js +1 -1
  169. package/lib/module/auth-card/AuthCard.js.map +1 -1
  170. package/lib/module/calendar/CalendarViewEventDetails.js +6 -1
  171. package/lib/module/calendar/CalendarViewEventDetails.js.map +1 -1
  172. package/lib/module/calendar/CalendarViewHeader.js +2 -1
  173. package/lib/module/calendar/CalendarViewHeader.js.map +1 -1
  174. package/lib/module/calendar/CalendarViewInboxMenu.js +3 -1
  175. package/lib/module/calendar/CalendarViewInboxMenu.js.map +1 -1
  176. package/lib/module/carousel/Carousel.js +2 -1
  177. package/lib/module/carousel/Carousel.js.map +1 -1
  178. package/lib/module/chart-cards/BarListCard.js +1 -1
  179. package/lib/module/chart-cards/BarListCard.js.map +1 -1
  180. package/lib/module/chart-cards/primitives/ChartRangePill.js +3 -1
  181. package/lib/module/chart-cards/primitives/ChartRangePill.js.map +1 -1
  182. package/lib/module/chat-indicators/MessageStatus.js +4 -1
  183. package/lib/module/chat-indicators/MessageStatus.js.map +1 -1
  184. package/lib/module/composer-panel/ComposerControls.js +60 -0
  185. package/lib/module/composer-panel/ComposerControls.js.map +1 -1
  186. package/lib/module/composer-panel/ComposerPanelBase.js +13 -5
  187. package/lib/module/composer-panel/ComposerPanelBase.js.map +1 -1
  188. package/lib/module/composer-panel/ComposerPillBase.js +115 -80
  189. package/lib/module/composer-panel/ComposerPillBase.js.map +1 -1
  190. package/lib/module/composer-panel/EffortSlider.js +24 -15
  191. package/lib/module/composer-panel/EffortSlider.js.map +1 -1
  192. package/lib/module/composer-panel/ModelPickerBase.js +15 -4
  193. package/lib/module/composer-panel/ModelPickerBase.js.map +1 -1
  194. package/lib/module/data-table/DataTableRowActions.js +1 -1
  195. package/lib/module/data-table/DataTableRowActions.js.map +1 -1
  196. package/lib/module/data-table/DataTableSearch.js +1 -1
  197. package/lib/module/data-table/DataTableSearch.js.map +1 -1
  198. package/lib/module/date-picker/MeetingScheduler.js +3 -1
  199. package/lib/module/date-picker/MeetingScheduler.js.map +1 -1
  200. package/lib/module/date-picker/PickerShell.js +1 -1
  201. package/lib/module/date-picker/PickerShell.js.map +1 -1
  202. package/lib/module/dialog/DialogHeader.js +9 -1
  203. package/lib/module/dialog/DialogHeader.js.map +1 -1
  204. package/lib/module/eviction/EvictionReportCard.js +8 -1
  205. package/lib/module/eviction/EvictionReportCard.js.map +1 -1
  206. package/lib/module/eviction/constants.js +8 -1
  207. package/lib/module/eviction/constants.js.map +1 -1
  208. package/lib/module/file-upload/FileUpload.js +4 -1
  209. package/lib/module/file-upload/FileUpload.js.map +1 -1
  210. package/lib/module/floating/menu-rows.js +1 -1
  211. package/lib/module/floating/menu-rows.js.map +1 -1
  212. package/lib/module/floating/menu-sub-flyout.js +1 -1
  213. package/lib/module/floating/menu-sub-flyout.js.map +1 -1
  214. package/lib/module/floating/menu-sub-inline.js +2 -1
  215. package/lib/module/floating/menu-sub-inline.js.map +1 -1
  216. package/lib/module/listing-card/ListingCard.js +2 -1
  217. package/lib/module/listing-card/ListingCard.js.map +1 -1
  218. package/lib/module/listing-details/ContactCard.js +5 -1
  219. package/lib/module/listing-details/ContactCard.js.map +1 -1
  220. package/lib/module/listing-details/FloorPlan.js +1 -1
  221. package/lib/module/listing-details/FloorPlan.js.map +1 -1
  222. package/lib/module/listing-details/ListingPhotoGrid.js +1 -1
  223. package/lib/module/listing-details/ListingPhotoGrid.js.map +1 -1
  224. package/lib/module/listing-details/ReviewCard.js +1 -1
  225. package/lib/module/listing-details/ReviewCard.js.map +1 -1
  226. package/lib/module/listing-details/ReviewSummary.js +1 -1
  227. package/lib/module/listing-details/ReviewSummary.js.map +1 -1
  228. package/lib/module/message-bubble/CallSummaryRow.js +4 -1
  229. package/lib/module/message-bubble/CallSummaryRow.js.map +1 -1
  230. package/lib/module/message-bubble/SwipeToReply.js +1 -1
  231. package/lib/module/message-bubble/SwipeToReply.js.map +1 -1
  232. package/lib/module/message-bubble/parts.js +4 -1
  233. package/lib/module/message-bubble/parts.js.map +1 -1
  234. package/lib/module/notification-center/NotificationCenter.js +5 -1
  235. package/lib/module/notification-center/NotificationCenter.js.map +1 -1
  236. package/lib/module/page-header/PageHeader.js +1 -1
  237. package/lib/module/page-header/PageHeader.js.map +1 -1
  238. package/lib/module/place-reviews/PlaceReviewCard.js +6 -1
  239. package/lib/module/place-reviews/PlaceReviewCard.js.map +1 -1
  240. package/lib/module/place-reviews/PlaceReviewSummary.js +2 -1
  241. package/lib/module/place-reviews/PlaceReviewSummary.js.map +1 -1
  242. package/lib/module/place-reviews/WriteReviewPrompt.js +3 -1
  243. package/lib/module/place-reviews/WriteReviewPrompt.js.map +1 -1
  244. package/lib/module/property-insights/EnergyBadge.js +1 -1
  245. package/lib/module/property-insights/EnergyBadge.js.map +1 -1
  246. package/lib/module/property-insights/EnergyLabel.js +1 -1
  247. package/lib/module/property-insights/EnergyLabel.js.map +1 -1
  248. package/lib/module/property-insights/NearbyPlaces.js +1 -1
  249. package/lib/module/property-insights/NearbyPlaces.js.map +1 -1
  250. package/lib/module/property-insights/PriceEstimate.js +2 -1
  251. package/lib/module/property-insights/PriceEstimate.js.map +1 -1
  252. package/lib/module/property-insights/PriceHistoryChart.js +1 -1
  253. package/lib/module/property-insights/PriceHistoryChart.js.map +1 -1
  254. package/lib/module/property-insights/RentHistoryList.js +1 -1
  255. package/lib/module/property-insights/RentHistoryList.js.map +1 -1
  256. package/lib/module/recent-hires-card/RecentHiresCard.js +2 -1
  257. package/lib/module/recent-hires-card/RecentHiresCard.js.map +1 -1
  258. package/lib/module/select/Select.js +1 -1
  259. package/lib/module/select/Select.js.map +1 -1
  260. package/lib/module/select/Select.web.js +1 -1
  261. package/lib/module/select/Select.web.js.map +1 -1
  262. package/lib/module/select/shared.js +2 -1
  263. package/lib/module/select/shared.js.map +1 -1
  264. package/lib/module/settings-modal/SettingsFields.js +1 -1
  265. package/lib/module/settings-modal/SettingsFields.js.map +1 -1
  266. package/lib/module/settings-modal/SettingsModal.js +4 -1
  267. package/lib/module/settings-modal/SettingsModal.js.map +1 -1
  268. package/lib/module/settings-modal/SettingsStorage.js +9 -1
  269. package/lib/module/settings-modal/SettingsStorage.js.map +1 -1
  270. package/lib/module/settings-modal/SettingsTools.js +2 -1
  271. package/lib/module/settings-modal/SettingsTools.js.map +1 -1
  272. package/lib/module/sidebar/Sidebar.js +3 -1
  273. package/lib/module/sidebar/Sidebar.js.map +1 -1
  274. package/lib/module/sidebar/SidebarFolder.js +2 -1
  275. package/lib/module/sidebar/SidebarFolder.js.map +1 -1
  276. package/lib/module/sidebar/SidebarUserMenu.js +2 -1
  277. package/lib/module/sidebar/SidebarUserMenu.js.map +1 -1
  278. package/lib/module/task-list/TaskList.js +1 -1
  279. package/lib/module/task-list/TaskList.js.map +1 -1
  280. package/lib/module/tenancy/DocumentList.js +3 -1
  281. package/lib/module/tenancy/DocumentList.js.map +1 -1
  282. package/lib/module/tenancy/MaintenanceRequestCard.js +1 -1
  283. package/lib/module/tenancy/MaintenanceRequestCard.js.map +1 -1
  284. package/lib/module/tenancy/RentPaymentList.js +1 -1
  285. package/lib/module/tenancy/RentPaymentList.js.map +1 -1
  286. package/lib/module/tenancy/constants.js +9 -1
  287. package/lib/module/tenancy/constants.js.map +1 -1
  288. package/lib/module/text-field/TextField.js +1 -1
  289. package/lib/module/text-field/TextField.js.map +1 -1
  290. package/lib/module/theme-toggle/ThemeToggle.js +2 -1
  291. package/lib/module/theme-toggle/ThemeToggle.js.map +1 -1
  292. package/lib/module/web-search/WebSearch.js +1 -1
  293. package/lib/module/web-search/WebSearch.js.map +1 -1
  294. package/lib/module/zoomable-media-gallery/ZoomableMediaGallery.js +5 -1
  295. package/lib/module/zoomable-media-gallery/ZoomableMediaGallery.js.map +1 -1
  296. package/lib/typescript/commonjs/agent-limits-card/AgentLimitsCard.d.ts.map +1 -1
  297. package/lib/typescript/commonjs/ai-chat/AiChatContainer.d.ts +28 -5
  298. package/lib/typescript/commonjs/ai-chat/AiChatContainer.d.ts.map +1 -1
  299. package/lib/typescript/commonjs/ai-chat/AiChatShell.d.ts +11 -2
  300. package/lib/typescript/commonjs/ai-chat/AiChatShell.d.ts.map +1 -1
  301. package/lib/typescript/commonjs/ai-chat/context.d.ts +19 -1
  302. package/lib/typescript/commonjs/ai-chat/context.d.ts.map +1 -1
  303. package/lib/typescript/commonjs/ai-chat/index.d.ts +3 -1
  304. package/lib/typescript/commonjs/ai-chat/index.d.ts.map +1 -1
  305. package/lib/typescript/commonjs/ai-chat/index.web.d.ts +3 -1
  306. package/lib/typescript/commonjs/ai-chat/index.web.d.ts.map +1 -1
  307. package/lib/typescript/commonjs/ai-chat/types.d.ts +101 -3
  308. package/lib/typescript/commonjs/ai-chat/types.d.ts.map +1 -1
  309. package/lib/typescript/commonjs/app-shell/AppShellHeader.d.ts.map +1 -1
  310. package/lib/typescript/commonjs/app-shell/AppShellMenuButton.d.ts.map +1 -1
  311. package/lib/typescript/commonjs/calendar/CalendarViewEventDetails.d.ts.map +1 -1
  312. package/lib/typescript/commonjs/calendar/CalendarViewHeader.d.ts.map +1 -1
  313. package/lib/typescript/commonjs/calendar/CalendarViewInboxMenu.d.ts.map +1 -1
  314. package/lib/typescript/commonjs/carousel/Carousel.d.ts.map +1 -1
  315. package/lib/typescript/commonjs/chart-cards/primitives/ChartRangePill.d.ts.map +1 -1
  316. package/lib/typescript/commonjs/chat-indicators/MessageStatus.d.ts.map +1 -1
  317. package/lib/typescript/commonjs/composer-panel/ComposerControls.d.ts +14 -0
  318. package/lib/typescript/commonjs/composer-panel/ComposerControls.d.ts.map +1 -1
  319. package/lib/typescript/commonjs/composer-panel/ComposerPanelBase.d.ts +3 -2
  320. package/lib/typescript/commonjs/composer-panel/ComposerPanelBase.d.ts.map +1 -1
  321. package/lib/typescript/commonjs/composer-panel/ComposerPillBase.d.ts +3 -2
  322. package/lib/typescript/commonjs/composer-panel/ComposerPillBase.d.ts.map +1 -1
  323. package/lib/typescript/commonjs/composer-panel/EffortSlider.d.ts +10 -2
  324. package/lib/typescript/commonjs/composer-panel/EffortSlider.d.ts.map +1 -1
  325. package/lib/typescript/commonjs/composer-panel/ModelPickerBase.d.ts.map +1 -1
  326. package/lib/typescript/commonjs/composer-panel/types.d.ts +61 -20
  327. package/lib/typescript/commonjs/composer-panel/types.d.ts.map +1 -1
  328. package/lib/typescript/commonjs/date-picker/MeetingScheduler.d.ts.map +1 -1
  329. package/lib/typescript/commonjs/dialog/DialogHeader.d.ts.map +1 -1
  330. package/lib/typescript/commonjs/eviction/EvictionReportCard.d.ts.map +1 -1
  331. package/lib/typescript/commonjs/eviction/constants.d.ts.map +1 -1
  332. package/lib/typescript/commonjs/file-upload/FileUpload.d.ts.map +1 -1
  333. package/lib/typescript/commonjs/floating/menu-sub-inline.d.ts.map +1 -1
  334. package/lib/typescript/commonjs/listing-card/ListingCard.d.ts.map +1 -1
  335. package/lib/typescript/commonjs/listing-details/ContactCard.d.ts.map +1 -1
  336. package/lib/typescript/commonjs/message-bubble/CallSummaryRow.d.ts.map +1 -1
  337. package/lib/typescript/commonjs/message-bubble/parts.d.ts.map +1 -1
  338. package/lib/typescript/commonjs/notification-center/NotificationCenter.d.ts.map +1 -1
  339. package/lib/typescript/commonjs/place-reviews/PlaceReviewCard.d.ts.map +1 -1
  340. package/lib/typescript/commonjs/place-reviews/PlaceReviewSummary.d.ts.map +1 -1
  341. package/lib/typescript/commonjs/place-reviews/WriteReviewPrompt.d.ts.map +1 -1
  342. package/lib/typescript/commonjs/property-insights/PriceEstimate.d.ts.map +1 -1
  343. package/lib/typescript/commonjs/recent-hires-card/RecentHiresCard.d.ts.map +1 -1
  344. package/lib/typescript/commonjs/select/shared.d.ts.map +1 -1
  345. package/lib/typescript/commonjs/settings-modal/SettingsModal.d.ts.map +1 -1
  346. package/lib/typescript/commonjs/settings-modal/SettingsStorage.d.ts.map +1 -1
  347. package/lib/typescript/commonjs/settings-modal/SettingsTools.d.ts.map +1 -1
  348. package/lib/typescript/commonjs/sidebar/Sidebar.d.ts.map +1 -1
  349. package/lib/typescript/commonjs/sidebar/SidebarFolder.d.ts.map +1 -1
  350. package/lib/typescript/commonjs/sidebar/SidebarUserMenu.d.ts.map +1 -1
  351. package/lib/typescript/commonjs/tenancy/DocumentList.d.ts.map +1 -1
  352. package/lib/typescript/commonjs/tenancy/constants.d.ts.map +1 -1
  353. package/lib/typescript/commonjs/theme-toggle/ThemeToggle.d.ts.map +1 -1
  354. package/lib/typescript/module/agent-limits-card/AgentLimitsCard.d.ts.map +1 -1
  355. package/lib/typescript/module/ai-chat/AiChatContainer.d.ts +28 -5
  356. package/lib/typescript/module/ai-chat/AiChatContainer.d.ts.map +1 -1
  357. package/lib/typescript/module/ai-chat/AiChatShell.d.ts +11 -2
  358. package/lib/typescript/module/ai-chat/AiChatShell.d.ts.map +1 -1
  359. package/lib/typescript/module/ai-chat/context.d.ts +19 -1
  360. package/lib/typescript/module/ai-chat/context.d.ts.map +1 -1
  361. package/lib/typescript/module/ai-chat/index.d.ts +3 -1
  362. package/lib/typescript/module/ai-chat/index.d.ts.map +1 -1
  363. package/lib/typescript/module/ai-chat/index.web.d.ts +3 -1
  364. package/lib/typescript/module/ai-chat/index.web.d.ts.map +1 -1
  365. package/lib/typescript/module/ai-chat/types.d.ts +101 -3
  366. package/lib/typescript/module/ai-chat/types.d.ts.map +1 -1
  367. package/lib/typescript/module/app-shell/AppShellHeader.d.ts.map +1 -1
  368. package/lib/typescript/module/app-shell/AppShellMenuButton.d.ts.map +1 -1
  369. package/lib/typescript/module/calendar/CalendarViewEventDetails.d.ts.map +1 -1
  370. package/lib/typescript/module/calendar/CalendarViewHeader.d.ts.map +1 -1
  371. package/lib/typescript/module/calendar/CalendarViewInboxMenu.d.ts.map +1 -1
  372. package/lib/typescript/module/carousel/Carousel.d.ts.map +1 -1
  373. package/lib/typescript/module/chart-cards/primitives/ChartRangePill.d.ts.map +1 -1
  374. package/lib/typescript/module/chat-indicators/MessageStatus.d.ts.map +1 -1
  375. package/lib/typescript/module/composer-panel/ComposerControls.d.ts +14 -0
  376. package/lib/typescript/module/composer-panel/ComposerControls.d.ts.map +1 -1
  377. package/lib/typescript/module/composer-panel/ComposerPanelBase.d.ts +3 -2
  378. package/lib/typescript/module/composer-panel/ComposerPanelBase.d.ts.map +1 -1
  379. package/lib/typescript/module/composer-panel/ComposerPillBase.d.ts +3 -2
  380. package/lib/typescript/module/composer-panel/ComposerPillBase.d.ts.map +1 -1
  381. package/lib/typescript/module/composer-panel/EffortSlider.d.ts +10 -2
  382. package/lib/typescript/module/composer-panel/EffortSlider.d.ts.map +1 -1
  383. package/lib/typescript/module/composer-panel/ModelPickerBase.d.ts.map +1 -1
  384. package/lib/typescript/module/composer-panel/types.d.ts +61 -20
  385. package/lib/typescript/module/composer-panel/types.d.ts.map +1 -1
  386. package/lib/typescript/module/date-picker/MeetingScheduler.d.ts.map +1 -1
  387. package/lib/typescript/module/dialog/DialogHeader.d.ts.map +1 -1
  388. package/lib/typescript/module/eviction/EvictionReportCard.d.ts.map +1 -1
  389. package/lib/typescript/module/eviction/constants.d.ts.map +1 -1
  390. package/lib/typescript/module/file-upload/FileUpload.d.ts.map +1 -1
  391. package/lib/typescript/module/floating/menu-sub-inline.d.ts.map +1 -1
  392. package/lib/typescript/module/listing-card/ListingCard.d.ts.map +1 -1
  393. package/lib/typescript/module/listing-details/ContactCard.d.ts.map +1 -1
  394. package/lib/typescript/module/message-bubble/CallSummaryRow.d.ts.map +1 -1
  395. package/lib/typescript/module/message-bubble/parts.d.ts.map +1 -1
  396. package/lib/typescript/module/notification-center/NotificationCenter.d.ts.map +1 -1
  397. package/lib/typescript/module/place-reviews/PlaceReviewCard.d.ts.map +1 -1
  398. package/lib/typescript/module/place-reviews/PlaceReviewSummary.d.ts.map +1 -1
  399. package/lib/typescript/module/place-reviews/WriteReviewPrompt.d.ts.map +1 -1
  400. package/lib/typescript/module/property-insights/PriceEstimate.d.ts.map +1 -1
  401. package/lib/typescript/module/recent-hires-card/RecentHiresCard.d.ts.map +1 -1
  402. package/lib/typescript/module/select/shared.d.ts.map +1 -1
  403. package/lib/typescript/module/settings-modal/SettingsModal.d.ts.map +1 -1
  404. package/lib/typescript/module/settings-modal/SettingsStorage.d.ts.map +1 -1
  405. package/lib/typescript/module/settings-modal/SettingsTools.d.ts.map +1 -1
  406. package/lib/typescript/module/sidebar/Sidebar.d.ts.map +1 -1
  407. package/lib/typescript/module/sidebar/SidebarFolder.d.ts.map +1 -1
  408. package/lib/typescript/module/sidebar/SidebarUserMenu.d.ts.map +1 -1
  409. package/lib/typescript/module/tenancy/DocumentList.d.ts.map +1 -1
  410. package/lib/typescript/module/tenancy/constants.d.ts.map +1 -1
  411. package/lib/typescript/module/theme-toggle/ThemeToggle.d.ts.map +1 -1
  412. package/package.json +1 -1
  413. package/src/__tests__/support/adoption-matrix.ts +664 -0
  414. package/src/__tests__/support/collision-fixture-barrel.ts +20 -0
  415. package/src/__tests__/support/composite.ts +68 -0
  416. package/src/__tests__/support/constructed-style-sheets.ts +68 -0
  417. package/src/__tests__/support/press-host.ts +30 -0
  418. package/src/__tests__/support/rendered-style.ts +99 -0
  419. package/src/__tests__/support/unread-hook-fixture.ts +33 -0
  420. package/src/agent-limits-card/AgentLimitsCard.tsx +3 -1
  421. package/src/ai-chat/AiChatContainer.tsx +137 -16
  422. package/src/ai-chat/AiChatShell.tsx +59 -5
  423. package/src/ai-chat/context.ts +19 -1
  424. package/src/ai-chat/index.ts +3 -0
  425. package/src/ai-chat/index.web.ts +3 -0
  426. package/src/ai-chat/types.ts +104 -3
  427. package/src/app-shell/AppShellHeader.tsx +2 -1
  428. package/src/app-shell/AppShellMenuButton.tsx +2 -1
  429. package/src/app-shell/NotificationBell.tsx +1 -1
  430. package/src/auth-card/AuthCard.tsx +1 -1
  431. package/src/calendar/CalendarViewEventDetails.tsx +6 -8
  432. package/src/calendar/CalendarViewHeader.tsx +2 -1
  433. package/src/calendar/CalendarViewInboxMenu.tsx +3 -1
  434. package/src/carousel/Carousel.tsx +2 -1
  435. package/src/chart-cards/BarListCard.tsx +1 -1
  436. package/src/chart-cards/primitives/ChartRangePill.tsx +3 -1
  437. package/src/chat-indicators/MessageStatus.tsx +4 -6
  438. package/src/composer-panel/ComposerControls.tsx +54 -0
  439. package/src/composer-panel/ComposerPanelBase.tsx +13 -5
  440. package/src/composer-panel/ComposerPillBase.tsx +101 -59
  441. package/src/composer-panel/EffortSlider.tsx +38 -18
  442. package/src/composer-panel/ModelPickerBase.tsx +23 -7
  443. package/src/composer-panel/types.ts +61 -20
  444. package/src/data-table/DataTableRowActions.tsx +1 -1
  445. package/src/data-table/DataTableSearch.tsx +1 -1
  446. package/src/date-picker/MeetingScheduler.tsx +3 -1
  447. package/src/date-picker/PickerShell.tsx +1 -1
  448. package/src/dialog/DialogHeader.tsx +8 -5
  449. package/src/eviction/EvictionReportCard.tsx +8 -10
  450. package/src/eviction/constants.ts +8 -10
  451. package/src/file-upload/FileUpload.tsx +4 -6
  452. package/src/floating/menu-rows.tsx +1 -1
  453. package/src/floating/menu-sub-flyout.tsx +1 -1
  454. package/src/floating/menu-sub-inline.tsx +2 -4
  455. package/src/listing-card/ListingCard.tsx +2 -1
  456. package/src/listing-details/ContactCard.tsx +5 -1
  457. package/src/listing-details/FloorPlan.tsx +1 -1
  458. package/src/listing-details/ListingPhotoGrid.tsx +1 -1
  459. package/src/listing-details/ReviewCard.tsx +1 -1
  460. package/src/listing-details/ReviewSummary.tsx +1 -1
  461. package/src/message-bubble/CallSummaryRow.tsx +4 -6
  462. package/src/message-bubble/SwipeToReply.tsx +1 -1
  463. package/src/message-bubble/parts.tsx +4 -1
  464. package/src/notification-center/NotificationCenter.tsx +5 -7
  465. package/src/page-header/PageHeader.tsx +1 -1
  466. package/src/place-reviews/PlaceReviewCard.tsx +6 -8
  467. package/src/place-reviews/PlaceReviewSummary.tsx +2 -1
  468. package/src/place-reviews/WriteReviewPrompt.tsx +3 -1
  469. package/src/property-insights/EnergyBadge.tsx +1 -1
  470. package/src/property-insights/EnergyLabel.tsx +1 -1
  471. package/src/property-insights/NearbyPlaces.tsx +1 -1
  472. package/src/property-insights/PriceEstimate.tsx +2 -1
  473. package/src/property-insights/PriceHistoryChart.tsx +1 -1
  474. package/src/property-insights/RentHistoryList.tsx +1 -1
  475. package/src/recent-hires-card/RecentHiresCard.tsx +2 -1
  476. package/src/select/Select.tsx +1 -1
  477. package/src/select/Select.web.tsx +1 -1
  478. package/src/select/shared.tsx +2 -4
  479. package/src/settings-modal/SettingsFields.tsx +1 -1
  480. package/src/settings-modal/SettingsModal.tsx +4 -1
  481. package/src/settings-modal/SettingsStorage.tsx +9 -11
  482. package/src/settings-modal/SettingsTools.tsx +2 -1
  483. package/src/sidebar/Sidebar.tsx +3 -1
  484. package/src/sidebar/SidebarFolder.tsx +2 -1
  485. package/src/sidebar/SidebarUserMenu.tsx +2 -1
  486. package/src/task-list/TaskList.tsx +1 -1
  487. package/src/tenancy/DocumentList.tsx +3 -1
  488. package/src/tenancy/MaintenanceRequestCard.tsx +1 -1
  489. package/src/tenancy/RentPaymentList.tsx +1 -1
  490. package/src/tenancy/constants.ts +9 -11
  491. package/src/text-field/TextField.tsx +1 -1
  492. package/src/theme/__tests__/__fixtures__/golden-resolved-tokens.json +7682 -0
  493. package/src/theme/__tests__/fixtures/color-engine-golden.json +1 -0
  494. package/src/theme-toggle/ThemeToggle.tsx +2 -1
  495. package/src/web-search/WebSearch.tsx +1 -1
  496. package/src/zoomable-media-gallery/ZoomableMediaGallery.tsx +5 -5
@@ -23,7 +23,7 @@ import type { WebCssStyle } from '../styles/web-view-style';
23
23
  import { useTheme } from '../theme/use-theme';
24
24
  import { Text, TYPE_SCALE } from '../typography';
25
25
  import { AddMenu } from './AddMenu';
26
- import { MicButton, SendButton } from './ComposerControls';
26
+ import { MicButton, SendButton, StopButton } from './ComposerControls';
27
27
  import { useComposerPopover } from './context';
28
28
  import { EffortSlider } from './EffortSlider';
29
29
  import {
@@ -35,7 +35,7 @@ import {
35
35
  resolveComposerPalette,
36
36
  type ComposerPalette,
37
37
  } from './shared';
38
- import type { ComposerPillLabels, ComposerPillProps } from './types';
38
+ import type { ComposerPillLabels, ComposerPillProps, ModelPickerModel } from './types';
39
39
  import { dataHook, IS_WEB, useComposerWebCss } from './web-hooks';
40
40
 
41
41
  const EASE = Easing.bezier(0.25, 0.1, 0.25, 1);
@@ -53,10 +53,12 @@ const DEFAULT_LABELS: Required<ComposerPillLabels> = {
53
53
  models: 'Models',
54
54
  modelGroup: 'Model',
55
55
  effort: 'Effort',
56
+ effortAuto: 'Auto',
56
57
  faster: 'Faster',
57
58
  smarter: 'Smarter',
58
59
  voice: 'Voice input',
59
60
  send: 'Send message',
61
+ stop: 'Stop generating',
60
62
  };
61
63
 
62
64
  /**
@@ -194,7 +196,10 @@ function ModelRow({
194
196
  *
195
197
  * models pt 4, label → rows 6: "Models" (pl 8, body-medium secondary), then a
196
198
  * radio row per model — p 8, radius 10, body-medium primary + 14px
197
- * radio, primary-hover while selected or hovered, 4 apart
199
+ * radio, primary-hover while selected or hovered, 4 apart. Rows key,
200
+ * match and report by id; a string entry is its own id
201
+ * effort only with stops to choose from — no `effortLevels`, no divider and
202
+ * no slider, rather than a slider that cannot commit
198
203
  * divider full bleed (−10 each side), 7 above, 12 below
199
204
  * effort "Effort <value>" (the value text-primary, blurring in on change),
200
205
  * Faster / Smarter (body-2-medium secondary, px 8 / pt 8 / pb 3) and
@@ -204,7 +209,7 @@ function ModelRow({
204
209
  */
205
210
  function ModelMenu({
206
211
  models,
207
- model,
212
+ modelId,
208
213
  onModelChange,
209
214
  effort,
210
215
  onEffortChange,
@@ -215,10 +220,10 @@ function ModelMenu({
215
220
  onTriggerLayout,
216
221
  testID,
217
222
  }: {
218
- models: ReadonlyArray<string>;
219
- model: string;
220
- onModelChange: (model: string) => void;
221
- effort: number;
223
+ models: ReadonlyArray<ModelPickerModel>;
224
+ modelId: string;
225
+ onModelChange: (modelId: string) => void;
226
+ effort: number | null;
222
227
  onEffortChange: (effort: number) => void;
223
228
  levels: ReadonlyArray<string>;
224
229
  labels: Required<ComposerPillLabels>;
@@ -231,6 +236,10 @@ function ModelMenu({
231
236
  const triggerRef = useRef<View>(null);
232
237
  const [open, setOpen] = useState(false);
233
238
  const [hovered, setHovered] = useState(false);
239
+ // An id with no entry (a model the lineup no longer carries) shows as itself
240
+ // rather than as an empty trigger.
241
+ const modelName = models.find((entry) => entry.id === modelId)?.name ?? modelId;
242
+ const hasEffort = levels.length > 0;
234
243
  const triggerStyle: WebCssStyle = {
235
244
  height: 32,
236
245
  flexShrink: 0,
@@ -254,7 +263,7 @@ function ModelMenu({
254
263
  testID={testID}
255
264
  {...dataHook('bloomComposerControl')}
256
265
  accessibilityRole="button"
257
- accessibilityLabel={model}
266
+ accessibilityLabel={modelName}
258
267
  aria-expanded={open}
259
268
  aria-haspopup="dialog"
260
269
  accessibilityState={{ expanded: open }}
@@ -264,7 +273,7 @@ function ModelMenu({
264
273
  onLayout={(event) => onTriggerLayout?.(event.nativeEvent.layout.width)}
265
274
  style={triggerStyle}>
266
275
  <Text variant="body-medium" numberOfLines={1} style={{ paddingLeft: 2, paddingRight: 2, color: palette.textSecondary }}>
267
- {model}
276
+ {modelName}
268
277
  </Text>
269
278
  <TurningChevron degrees={open ? 180 : 0} color={palette.iconSecondary} />
270
279
  </Pressable>
@@ -292,52 +301,63 @@ function ModelMenu({
292
301
  {labels.models}
293
302
  </Text>
294
303
  <View role="radiogroup" accessibilityLabel={labels.modelGroup} style={{ width: '100%', flexDirection: 'column', gap: 4 }}>
295
- {models.map((name) => (
304
+ {models.map((entry) => (
296
305
  <ModelRow
297
- key={name}
298
- name={name}
299
- selected={name === model}
306
+ key={entry.id}
307
+ name={entry.name}
308
+ selected={entry.id === modelId}
300
309
  palette={palette}
301
310
  onPress={() => {
302
- onModelChange(name);
311
+ onModelChange(entry.id);
303
312
  setOpen(false);
304
313
  }}
305
314
  />
306
315
  ))}
307
316
  </View>
308
317
  </View>
309
- <View style={{ height: 1, marginLeft: -10, marginRight: -10, marginTop: 7, marginBottom: 12, backgroundColor: palette.border }} />
310
- <View style={{ width: '100%', flexDirection: 'column' }}>
311
- <View style={{ flexDirection: 'row', alignItems: 'center', paddingLeft: 8 }}>
312
- <Text variant="body-medium" style={{ color: palette.textSecondary }}>
313
- {`${labels.effort} `}
314
- </Text>
315
- <EffortValue value={levels[effort] ?? ''} color={palette.text} />
316
- </View>
317
- <View style={{ width: '100%', flexDirection: 'column', gap: 4 }}>
318
- <View
319
- style={{
320
- width: '100%',
321
- flexDirection: 'row',
322
- alignItems: 'center',
323
- justifyContent: 'space-between',
324
- paddingLeft: 8,
325
- paddingRight: 8,
326
- paddingTop: 8,
327
- paddingBottom: 3,
328
- }}>
329
- <Text variant="body-2-medium" style={{ color: palette.textSecondary }}>
330
- {labels.faster}
331
- </Text>
332
- <Text variant="body-2-medium" style={{ color: palette.textSecondary }}>
333
- {labels.smarter}
334
- </Text>
335
- </View>
336
- <View style={{ width: '100%', paddingLeft: 8, paddingRight: 8, paddingBottom: 8 }}>
337
- <EffortSlider value={effort} onChange={onEffortChange} levels={levels} label={labels.effort} palette={palette} />
318
+ {hasEffort ? (
319
+ <>
320
+ <View style={{ height: 1, marginLeft: -10, marginRight: -10, marginTop: 7, marginBottom: 12, backgroundColor: palette.border }} />
321
+ <View style={{ width: '100%', flexDirection: 'column' }}>
322
+ <View style={{ flexDirection: 'row', alignItems: 'center', paddingLeft: 8 }}>
323
+ <Text variant="body-medium" style={{ color: palette.textSecondary }}>
324
+ {`${labels.effort} `}
325
+ </Text>
326
+ <EffortValue value={effort === null ? labels.effortAuto : (levels[effort] ?? labels.effortAuto)} color={palette.text} />
327
+ </View>
328
+ <View style={{ width: '100%', flexDirection: 'column', gap: 4 }}>
329
+ <View
330
+ style={{
331
+ width: '100%',
332
+ flexDirection: 'row',
333
+ alignItems: 'center',
334
+ justifyContent: 'space-between',
335
+ paddingLeft: 8,
336
+ paddingRight: 8,
337
+ paddingTop: 8,
338
+ paddingBottom: 3,
339
+ }}>
340
+ <Text variant="body-2-medium" style={{ color: palette.textSecondary }}>
341
+ {labels.faster}
342
+ </Text>
343
+ <Text variant="body-2-medium" style={{ color: palette.textSecondary }}>
344
+ {labels.smarter}
345
+ </Text>
346
+ </View>
347
+ <View style={{ width: '100%', paddingLeft: 8, paddingRight: 8, paddingBottom: 8 }}>
348
+ <EffortSlider
349
+ value={effort}
350
+ onChange={onEffortChange}
351
+ levels={levels}
352
+ label={labels.effort}
353
+ unsetLabel={labels.effortAuto}
354
+ palette={palette}
355
+ />
356
+ </View>
357
+ </View>
338
358
  </View>
339
- </View>
340
- </View>
359
+ </>
360
+ ) : null}
341
361
  </Popover>
342
362
  </>
343
363
  );
@@ -355,7 +375,8 @@ function ModelMenu({
355
375
  * unfocused on web, its last 32px fade into the pill
356
376
  * model the model menu trigger (see `ModelMenu`)
357
377
  * controls pl 6, gap 8: the bordered mic (dancing accent bars while
358
- * listening) and the `bg-button-primary` send disc
378
+ * listening) and the `bg-button-primary` send disc — which becomes
379
+ * the stop disc while `busy`, outside `disabled`'s reach
359
380
  *
360
381
  * `glass` drops the add, model and mic paint (480ms) onto frosted chips, so an
361
382
  * active `ComposerLoader` behind the pill shows through them.
@@ -365,6 +386,8 @@ export function ComposerPillBase({
365
386
  defaultValue = '',
366
387
  onValueChange,
367
388
  onSubmit,
389
+ onStop,
390
+ busy = false,
368
391
  disabled = false,
369
392
  placeholder = 'Ask me anything',
370
393
  compactPlaceholder = 'Ask me',
@@ -400,15 +423,19 @@ export function ComposerPillBase({
400
423
  defaultValue: defaultListening,
401
424
  onChange: onListeningChange,
402
425
  });
403
- const [modelName, setModel] = useControllableState<string>({
426
+ const lineup = useMemo(() => normalizeModels(models ?? []), [models]);
427
+ const [modelId, setModel] = useControllableState<string>({
404
428
  value: model,
405
- defaultValue: defaultModel ?? models?.[0] ?? '',
429
+ defaultValue: defaultModel ?? lineup[0]?.id ?? '',
406
430
  onChange: onModelChange,
407
431
  });
408
- const [effortValue, setEffort] = useControllableState<number>({
432
+ const [effortValue, setEffort] = useControllableState<number | null>({
409
433
  value: effort,
410
434
  defaultValue: defaultEffort,
411
- onChange: onEffortChange,
435
+ // The menu can only ever land on a stop; `null` is the caller's to hold.
436
+ onChange: (next) => {
437
+ if (next !== null) onEffortChange?.(next);
438
+ },
412
439
  });
413
440
  const [focused, setFocused] = useState(false);
414
441
  const [modelWidth, setModelWidth] = useState(0);
@@ -433,18 +460,18 @@ export function ComposerPillBase({
433
460
  );
434
461
 
435
462
  const submit = useCallback(() => {
436
- if (disabled) return;
463
+ if (disabled || busy) return;
437
464
  onSubmit?.(text);
438
- }, [disabled, onSubmit, text]);
465
+ }, [disabled, busy, onSubmit, text]);
439
466
 
440
467
  const onKeyPress = useCallback(
441
468
  (event: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
442
469
  const native: TextInputKeyPressEventData & { isComposing?: boolean } = event.nativeEvent;
443
- if (!IS_WEB || native.key !== 'Enter' || native.isComposing || disabled) return;
470
+ if (!IS_WEB || native.key !== 'Enter' || native.isComposing || disabled || busy) return;
444
471
  event.preventDefault();
445
472
  submit();
446
473
  },
447
- [submit, disabled],
474
+ [submit, disabled, busy],
448
475
  );
449
476
 
450
477
  const pillStyle: WebCssStyle = {
@@ -518,12 +545,12 @@ export function ComposerPillBase({
518
545
  />
519
546
  </View>
520
547
 
521
- {models && models.length > 0 ? (
548
+ {lineup.length > 0 ? (
522
549
  <View style={{ position: 'relative', flexShrink: 0 }}>
523
550
  <GlassChip shown={glass && modelWidth > 0} radius={12} dark={theme.isDark} />
524
551
  <ModelMenu
525
- models={models}
526
- model={modelName}
552
+ models={lineup}
553
+ modelId={modelId}
527
554
  onModelChange={setModel}
528
555
  effort={effortValue}
529
556
  onEffortChange={setEffort}
@@ -547,7 +574,11 @@ export function ComposerPillBase({
547
574
  palette={controlPalette}
548
575
  />
549
576
  </View>
550
- <SendButton disabled={disabled} onPress={submit} label={labels.send} palette={palette} />
577
+ {busy && onStop ? (
578
+ <StopButton onPress={onStop} label={labels.stop} palette={palette} />
579
+ ) : (
580
+ <SendButton disabled={disabled} onPress={submit} label={labels.send} palette={palette} />
581
+ )}
551
582
  </View>
552
583
  </View>
553
584
  );
@@ -562,5 +593,16 @@ const DEFAULT_PANEL_LABELS = {
562
593
  learnMore: 'Learn more',
563
594
  voice: 'Voice input',
564
595
  send: 'Send message',
596
+ stop: 'Stop generating',
565
597
  remove: 'Remove',
566
598
  };
599
+
600
+ /**
601
+ * A bare string entry is its own id: the shorthand stays exact, and an `{ id,
602
+ * name }` entry keys, matches and reports by id like `ModelPicker` does.
603
+ */
604
+ function normalizeModels(
605
+ models: ReadonlyArray<string | ModelPickerModel>,
606
+ ): ReadonlyArray<ModelPickerModel> {
607
+ return models.map((entry) => (typeof entry === 'string' ? { id: entry, name: entry } : entry));
608
+ }
@@ -9,10 +9,13 @@ const TRACK_HEIGHT = 27;
9
9
  const THUMB_WIDTH = 21;
10
10
 
11
11
  interface EffortSliderProps {
12
- value: number;
12
+ /** The chosen stop, or `null` for no choice yet. */
13
+ value: number | null;
13
14
  onChange: (value: number) => void;
14
15
  levels: ReadonlyArray<string>;
15
16
  label: string;
17
+ /** What `aria-valuetext` reads with no stop chosen (the "Auto" label). */
18
+ unsetLabel: string;
16
19
  palette: ComposerPalette;
17
20
  testID?: string;
18
21
  }
@@ -25,6 +28,11 @@ interface EffortSliderProps {
25
28
  * past the value fade their tick to 30% over 300ms; the fill follows the thumb
26
29
  * over 150ms.
27
30
  *
31
+ * With `value` `null` nothing is committed: the fill is empty, every tick is
32
+ * faded and the thumb is hollow and dashed, so "no stop chosen" cannot be read
33
+ * as "the first stop". The first press or key commits a stop, and there is no
34
+ * way back — the caller owns the `null`.
35
+ *
28
36
  * Drag or press anywhere on the track (PanResponder on both platforms); on web
29
37
  * the thumb is focusable and answers the arrow keys, Home and End.
30
38
  *
@@ -32,20 +40,25 @@ interface EffortSliderProps {
32
40
  * starfield, with the ticks blown off the track) has no native counterpart,
33
41
  * so at Max the slider simply rests at its last stop.
34
42
  */
35
- export function EffortSlider({ value, onChange, levels, label, palette, testID }: EffortSliderProps) {
43
+ export function EffortSlider({ value, onChange, levels, label, unsetLabel, palette, testID }: EffortSliderProps) {
36
44
  const [width, setWidth] = useState(0);
37
45
  const max = Math.max(0, levels.length - 1);
38
- const clamped = Math.min(Math.max(value, 0), max);
39
- const fraction = max > 0 ? clamped / max : 0;
46
+ const chosen = value === null ? null : Math.min(Math.max(value, 0), max);
47
+ const fraction = chosen !== null && max > 0 ? chosen / max : 0;
40
48
  const rail = Math.max(0, width - THUMB_WIDTH);
41
49
 
42
- const stateRef = useRef({ value: clamped, rail, max, onChange });
43
- stateRef.current = { value: clamped, rail, max, onChange };
44
- const startRef = useRef(clamped);
50
+ const stateRef = useRef<{ value: number | null; rail: number; max: number; onChange: (next: number) => void }>({
51
+ value: chosen,
52
+ rail,
53
+ max,
54
+ onChange,
55
+ });
56
+ stateRef.current = { value: chosen, rail, max, onChange };
57
+ const startRef = useRef(chosen ?? 0);
45
58
 
46
59
  const valueAt = useCallback((x: number) => {
47
60
  const s = stateRef.current;
48
- if (s.rail <= 0 || s.max <= 0) return s.value;
61
+ if (s.rail <= 0 || s.max <= 0) return s.value ?? 0;
49
62
  const f = Math.min(Math.max((x - THUMB_WIDTH / 2) / s.rail, 0), 1);
50
63
  return Math.round(f * s.max);
51
64
  }, []);
@@ -83,11 +96,17 @@ export function EffortSlider({ value, onChange, levels, label, palette, testID }
83
96
  tabIndex: 0,
84
97
  onKeyDown: (event: { key: string; preventDefault: () => void }) => {
85
98
  const s = stateRef.current;
99
+ // With nothing chosen, either arrow commits the first stop.
100
+ const current = s.value;
86
101
  const next =
87
102
  event.key === 'ArrowRight' || event.key === 'ArrowUp'
88
- ? Math.min(s.max, s.value + 1)
103
+ ? current === null
104
+ ? 0
105
+ : Math.min(s.max, current + 1)
89
106
  : event.key === 'ArrowLeft' || event.key === 'ArrowDown'
90
- ? Math.max(0, s.value - 1)
107
+ ? current === null
108
+ ? 0
109
+ : Math.max(0, current - 1)
91
110
  : event.key === 'Home'
92
111
  ? 0
93
112
  : event.key === 'End'
@@ -108,9 +127,10 @@ export function EffortSlider({ value, onChange, levels, label, palette, testID }
108
127
  height: TRACK_HEIGHT,
109
128
  borderRadius: 7,
110
129
  borderWidth: 1,
130
+ borderStyle: chosen === null ? 'dashed' : 'solid',
111
131
  borderColor: palette.thumbBorder,
112
- backgroundColor: palette.surface,
113
- boxShadow: palette.shadowXs,
132
+ backgroundColor: chosen === null ? 'transparent' : palette.surface,
133
+ boxShadow: chosen === null ? undefined : palette.shadowXs,
114
134
  '--bloom-composer-ring': palette.focusRing,
115
135
  };
116
136
 
@@ -121,12 +141,12 @@ export function EffortSlider({ value, onChange, levels, label, palette, testID }
121
141
  accessibilityLabel={label}
122
142
  aria-valuemin={0}
123
143
  aria-valuemax={max}
124
- aria-valuenow={clamped}
125
- aria-valuetext={levels[clamped]}
144
+ aria-valuenow={chosen ?? undefined}
145
+ aria-valuetext={chosen === null ? unsetLabel : levels[chosen]}
126
146
  accessibilityActions={[{ name: 'increment' }, { name: 'decrement' }]}
127
147
  onAccessibilityAction={(event) => {
128
- if (event.nativeEvent.actionName === 'increment') commit(Math.min(max, clamped + 1));
129
- if (event.nativeEvent.actionName === 'decrement') commit(Math.max(0, clamped - 1));
148
+ if (event.nativeEvent.actionName === 'increment') commit(chosen === null ? 0 : Math.min(max, chosen + 1));
149
+ if (event.nativeEvent.actionName === 'decrement') commit(chosen === null ? 0 : Math.max(0, chosen - 1));
130
150
  }}
131
151
  style={{ width: '100%' }}>
132
152
  <View
@@ -149,7 +169,7 @@ export function EffortSlider({ value, onChange, levels, label, palette, testID }
149
169
  top: 0,
150
170
  bottom: 0,
151
171
  left: 0,
152
- width: fraction * rail + THUMB_WIDTH,
172
+ width: chosen === null ? 0 : fraction * rail + THUMB_WIDTH,
153
173
  borderRadius: 8,
154
174
  backgroundColor: palette.tertiaryHover,
155
175
  }}
@@ -175,7 +195,7 @@ export function EffortSlider({ value, onChange, levels, label, palette, testID }
175
195
  height: 13,
176
196
  borderRadius: 2,
177
197
  backgroundColor: palette.iconTertiary,
178
- opacity: index > clamped ? 0.3 : 1,
198
+ opacity: chosen === null || index > chosen ? 0.3 : 1,
179
199
  }}
180
200
  />
181
201
  ))}
@@ -57,6 +57,7 @@ const DEFAULT_LABELS: Required<ModelPickerLabels> = {
57
57
  noMatches: 'No models match',
58
58
  providers: 'Providers',
59
59
  effort: 'Effort',
60
+ effortAuto: 'Auto',
60
61
  faster: 'Faster',
61
62
  smarter: 'Smarter',
62
63
  };
@@ -218,6 +219,11 @@ function BlurInLevel({ level, palette }: { level: string; palette: ComposerPalet
218
219
  );
219
220
  }
220
221
 
222
+ /**
223
+ * The effort chip on the checked row. Drawn only where there are stops to
224
+ * choose from — a model with no effort axis gets no chip, rather than an empty
225
+ * one over a slider that cannot commit.
226
+ */
221
227
  function EffortMenu({
222
228
  value,
223
229
  onChange,
@@ -225,7 +231,7 @@ function EffortMenu({
225
231
  labels,
226
232
  palette,
227
233
  }: {
228
- value: number;
234
+ value: number | null;
229
235
  onChange: (next: number) => void;
230
236
  levels: ReadonlyArray<string>;
231
237
  labels: Required<ModelPickerLabels>;
@@ -235,7 +241,7 @@ function EffortMenu({
235
241
  const triggerRef = useRef<View>(null);
236
242
  const [open, setOpen] = useState(false);
237
243
  const [hovered, setHovered] = useState(false);
238
- const level = levels[value] ?? levels[DEFAULT_EFFORT] ?? '';
244
+ const level = value === null ? labels.effortAuto : (levels[value] ?? labels.effortAuto);
239
245
 
240
246
  const chipStyle: WebCssStyle = {
241
247
  flexShrink: 0,
@@ -314,7 +320,14 @@ function EffortMenu({
314
320
  </Text>
315
321
  </View>
316
322
  <View style={{ paddingLeft: 8, paddingRight: 8, paddingBottom: 8 }}>
317
- <EffortSlider value={value} onChange={onChange} levels={levels} label={labels.effort} palette={palette} />
323
+ <EffortSlider
324
+ value={value}
325
+ onChange={onChange}
326
+ levels={levels}
327
+ label={labels.effort}
328
+ unsetLabel={labels.effortAuto}
329
+ palette={palette}
330
+ />
318
331
  </View>
319
332
  </View>
320
333
  </View>
@@ -388,7 +401,7 @@ function ModelRow({
388
401
  {searching ? <InlineAside color={palette.textTertiary}>{provider.name}</InlineAside> : null}
389
402
  </Text>
390
403
  </View>
391
- {checked ? <View style={{ flexShrink: 0, flexDirection: 'row' }}>{effort}</View> : null}
404
+ {effort ? <View style={{ flexShrink: 0, flexDirection: 'row' }}>{effort}</View> : null}
392
405
  </View>
393
406
  <View pointerEvents="none">
394
407
  <RadioIndicator selected={checked} size={14} />
@@ -447,10 +460,13 @@ export function ModelPickerBase({
447
460
  defaultValue: defaultValue ?? providers[0]?.models[0]?.id ?? '',
448
461
  onChange: onValueChange,
449
462
  });
450
- const [effortValue, setEffort] = useControllableState<number>({
463
+ const [effortValue, setEffort] = useControllableState<number | null>({
451
464
  value: effort,
452
465
  defaultValue: defaultEffort,
453
- onChange: onEffortChange,
466
+ // The picker can only ever land on a stop; `null` is the caller's to hold.
467
+ onChange: (next) => {
468
+ if (next !== null) onEffortChange?.(next);
469
+ },
454
470
  });
455
471
 
456
472
  const selected: Match | null =
@@ -724,7 +740,7 @@ export function ModelPickerBase({
724
740
  }
725
741
  }}
726
742
  effort={
727
- checked ? (
743
+ checked && effortLevels.length > 0 ? (
728
744
  <EffortMenu
729
745
  value={effortValue}
730
746
  onChange={setEffort}
@@ -121,6 +121,8 @@ export interface ModelPickerLabels {
121
121
  providers?: string;
122
122
  /** Default `'Effort'`. */
123
123
  effort?: string;
124
+ /** Default `'Auto'` — the effort chip with no stop chosen. */
125
+ effortAuto?: string;
124
126
  /** Default `'Faster'`. */
125
127
  faster?: string;
126
128
  /** Default `'Smarter'`. */
@@ -135,12 +137,17 @@ export interface ModelPickerProps {
135
137
  /** Initial model id when uncontrolled. Defaults to the first provider's first model. */
136
138
  defaultValue?: string;
137
139
  onValueChange?: (modelId: string) => void;
138
- /** Controlled effort stop, an index into `effortLevels`. */
139
- effort?: number;
140
- /** Initial stop when uncontrolled. Default `1` ("Medium"). */
141
- defaultEffort?: number;
140
+ /**
141
+ * Controlled effort stop, an index into `effortLevels`. `null` is "no stop
142
+ * chosen" — the chip reads `labels.effortAuto`, the slider commits nothing and
143
+ * the thumb is drawn hollow, so the absence of a choice never looks like one.
144
+ */
145
+ effort?: number | null;
146
+ /** Initial stop when uncontrolled. Default `1` ("Medium"); `null` for no choice. */
147
+ defaultEffort?: number | null;
148
+ /** A stop the reader chose. The picker has no way back to `null`, so it never reports one. */
142
149
  onEffortChange?: (effort: number) => void;
143
- /** The effort stops, "Faster" → "Smarter". Defaults to six stops. */
150
+ /** The effort stops, "Faster" → "Smarter". Defaults to six stops; `[]` drops the effort axis entirely. */
144
151
  effortLevels?: ReadonlyArray<string>;
145
152
  labels?: ModelPickerLabels;
146
153
  style?: StyleProp<ViewStyle>;
@@ -169,6 +176,8 @@ export interface ComposerPanelLabels {
169
176
  voice?: string;
170
177
  /** Default `'Send message'`. */
171
178
  send?: string;
179
+ /** Default `'Stop generating'` — send's stop state while `busy`. */
180
+ stop?: string;
172
181
  /** Default `'Remove'` — prefixed to the file name on a tile's dismiss. */
173
182
  remove?: string;
174
183
  }
@@ -181,7 +190,15 @@ export interface ComposerPanelProps {
181
190
  onValueChange?: (value: string) => void;
182
191
  /** Fires on the send button and on Enter (web; Shift+Enter breaks the line). */
183
192
  onSubmit?: (value: string) => void;
184
- /** Greys out send while a turn is in flight. */
193
+ /**
194
+ * Stop the turn in flight. With `busy`, send becomes a stop control that
195
+ * ignores `disabled` — cancelling has to stay possible while typing is not.
196
+ * Without a handler `busy` draws no stop, so the control is never inert.
197
+ */
198
+ onStop?: () => void;
199
+ /** A turn is running: send becomes stop (given `onStop`) and Enter no longer submits. */
200
+ busy?: boolean;
201
+ /** Greys out send while a turn is in flight. Never reaches the stop control. */
185
202
  disabled?: boolean;
186
203
  /** Default `'Hi, what do you need today?'`. */
187
204
  placeholder?: string;
@@ -207,10 +224,11 @@ export interface ComposerPanelProps {
207
224
  model?: string;
208
225
  defaultModel?: string;
209
226
  onModelChange?: (modelId: string) => void;
210
- /** Controlled effort stop. */
211
- effort?: number;
212
- defaultEffort?: number;
227
+ /** Controlled effort stop; `null` is "no stop chosen". See `ModelPicker`. */
228
+ effort?: number | null;
229
+ defaultEffort?: number | null;
213
230
  onEffortChange?: (effort: number) => void;
231
+ /** `[]` drops the effort axis from the picker. */
214
232
  effortLevels?: ReadonlyArray<string>;
215
233
  modelPickerLabels?: ModelPickerLabels;
216
234
 
@@ -293,6 +311,8 @@ export interface ComposerPillLabels {
293
311
  modelGroup?: string;
294
312
  /** Default `'Effort'`. */
295
313
  effort?: string;
314
+ /** Default `'Auto'` — the effort value with no stop chosen. */
315
+ effortAuto?: string;
296
316
  /** Default `'Faster'`. */
297
317
  faster?: string;
298
318
  /** Default `'Smarter'`. */
@@ -301,6 +321,8 @@ export interface ComposerPillLabels {
301
321
  voice?: string;
302
322
  /** Default `'Send message'`. */
303
323
  send?: string;
324
+ /** Default `'Stop generating'` — send's stop state while `busy`. */
325
+ stop?: string;
304
326
  }
305
327
 
306
328
  export interface ComposerPillProps {
@@ -311,7 +333,15 @@ export interface ComposerPillProps {
311
333
  onValueChange?: (value: string) => void;
312
334
  /** Fires on the send button and on Enter. */
313
335
  onSubmit?: (value: string) => void;
314
- /** Greys out send (40%) while a turn is in flight. */
336
+ /**
337
+ * Stop the turn in flight. With `busy`, send becomes a stop control that
338
+ * ignores `disabled` — cancelling has to stay possible while typing is not.
339
+ * Without a handler `busy` draws no stop, so the control is never inert.
340
+ */
341
+ onStop?: () => void;
342
+ /** A turn is running: send becomes stop (given `onStop`) and Enter no longer submits. */
343
+ busy?: boolean;
344
+ /** Greys out send (40%) while a turn is in flight. Never reaches the stop control. */
315
345
  disabled?: boolean;
316
346
  /** Default `'Ask me anything'`. */
317
347
  placeholder?: string;
@@ -322,19 +352,30 @@ export interface ComposerPillProps {
322
352
  addMenu?: ReadonlyArray<ComposerPanelAddMenuGroup>;
323
353
  onAddMenuSelect?: (rowId: string) => void;
324
354
 
325
- /** Model names for the model menu. Omit to hide the model button. */
326
- models?: ReadonlyArray<string>;
327
- /** Controlled model name. */
355
+ /**
356
+ * The model menu's lineup. Omit to hide the model button.
357
+ *
358
+ * `{ id, name }` entries are the identity contract `ModelPicker` uses: the
359
+ * menu keys, matches and reports the **id**, and draws the `name`. A bare
360
+ * string is shorthand for `{ id: name, name }` — kept so the display-name form
361
+ * still works, and the only form in which a routing id is a display string.
362
+ */
363
+ models?: ReadonlyArray<string | ModelPickerModel>;
364
+ /** Controlled model **id** (a string entry's id is its name). */
328
365
  model?: string;
329
- /** Initial model when uncontrolled. Default the first. */
366
+ /** Initial model id when uncontrolled. Default the first entry's. */
330
367
  defaultModel?: string;
331
- onModelChange?: (model: string) => void;
332
- /** Controlled effort stop, an index into `effortLevels`. */
333
- effort?: number;
334
- /** Default `1` ("Medium"). */
335
- defaultEffort?: number;
368
+ onModelChange?: (modelId: string) => void;
369
+ /**
370
+ * Controlled effort stop, an index into `effortLevels`. `null` is "no stop
371
+ * chosen" — the value reads `labels.effortAuto` and the thumb is drawn hollow.
372
+ */
373
+ effort?: number | null;
374
+ /** Default `1` ("Medium"); `null` for no choice. */
375
+ defaultEffort?: number | null;
376
+ /** A stop the reader chose. The menu has no way back to `null`, so it never reports one. */
336
377
  onEffortChange?: (effort: number) => void;
337
- /** Default `MODEL_PICKER_EFFORT_LEVELS`. */
378
+ /** Default `MODEL_PICKER_EFFORT_LEVELS`; `[]` drops the effort half of the menu. */
338
379
  effortLevels?: ReadonlyArray<string>;
339
380
 
340
381
  /** Controlled voice-input state (the mic swaps to equalizer bars). */