@moldable-ai/ui 0.2.19 → 0.2.20

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 (372) hide show
  1. package/dist/catalog/catalog-manifest.d.ts +6 -0
  2. package/dist/catalog/catalog-manifest.d.ts.map +1 -0
  3. package/dist/catalog/catalog-manifest.js +105 -0
  4. package/dist/catalog/catalog-types.d.ts +54 -0
  5. package/dist/catalog/catalog-types.d.ts.map +1 -0
  6. package/dist/catalog/catalog-types.js +14 -0
  7. package/dist/catalog/component-catalog.d.ts +14 -0
  8. package/dist/catalog/component-catalog.d.ts.map +1 -0
  9. package/dist/catalog/component-catalog.js +39 -0
  10. package/dist/catalog/core-catalog.d.ts +6 -0
  11. package/dist/catalog/core-catalog.d.ts.map +1 -0
  12. package/dist/catalog/core-catalog.js +105 -0
  13. package/dist/catalog/index.d.ts +5 -0
  14. package/dist/catalog/index.d.ts.map +1 -0
  15. package/dist/catalog/index.js +4 -0
  16. package/dist/components/app-error-boundary.d.ts +1 -0
  17. package/dist/components/app-error-boundary.d.ts.map +1 -1
  18. package/dist/components/app-error-boundary.js +13 -0
  19. package/dist/components/chat/chat-image-lightbox.d.ts +9 -0
  20. package/dist/components/chat/chat-image-lightbox.d.ts.map +1 -0
  21. package/dist/components/chat/chat-image-lightbox.js +9 -0
  22. package/dist/components/chat/chat-message.d.ts +19 -1
  23. package/dist/components/chat/chat-message.d.ts.map +1 -1
  24. package/dist/components/chat/chat-message.js +66 -16
  25. package/dist/components/chat/chat-messages.d.ts +5 -2
  26. package/dist/components/chat/chat-messages.d.ts.map +1 -1
  27. package/dist/components/chat/chat-messages.js +61 -6
  28. package/dist/components/chat/chat-panel.d.ts +50 -6
  29. package/dist/components/chat/chat-panel.d.ts.map +1 -1
  30. package/dist/components/chat/chat-panel.js +200 -163
  31. package/dist/components/chat/conversation-history.d.ts +39 -5
  32. package/dist/components/chat/conversation-history.d.ts.map +1 -1
  33. package/dist/components/chat/conversation-history.js +192 -26
  34. package/dist/components/chat/index.d.ts +2 -2
  35. package/dist/components/chat/index.d.ts.map +1 -1
  36. package/dist/components/chat/index.js +1 -1
  37. package/dist/components/chat/tool-handlers.d.ts.map +1 -1
  38. package/dist/components/chat/tool-handlers.js +40 -2
  39. package/dist/components/chat/vertical-scroll-fade.d.ts +6 -0
  40. package/dist/components/chat/vertical-scroll-fade.d.ts.map +1 -0
  41. package/dist/components/chat/vertical-scroll-fade.js +12 -0
  42. package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts +9 -0
  43. package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts.map +1 -0
  44. package/dist/components/native-capabilities/bluetooth-panel-helpers.js +37 -0
  45. package/dist/components/native-capabilities/bluetooth-panel.d.ts +56 -0
  46. package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -0
  47. package/dist/components/native-capabilities/bluetooth-panel.js +470 -0
  48. package/dist/components/native-capabilities/camera-preview.d.ts +39 -0
  49. package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -0
  50. package/dist/components/native-capabilities/camera-preview.js +228 -0
  51. package/dist/components/native-capabilities/capability-badge.d.ts +23 -0
  52. package/dist/components/native-capabilities/capability-badge.d.ts.map +1 -0
  53. package/dist/components/native-capabilities/capability-badge.js +39 -0
  54. package/dist/components/native-capabilities/capability-matrix.d.ts +14 -0
  55. package/dist/components/native-capabilities/capability-matrix.d.ts.map +1 -0
  56. package/dist/components/native-capabilities/capability-matrix.js +97 -0
  57. package/dist/components/native-capabilities/clipboard-button.d.ts +26 -0
  58. package/dist/components/native-capabilities/clipboard-button.d.ts.map +1 -0
  59. package/dist/components/native-capabilities/clipboard-button.js +99 -0
  60. package/dist/components/native-capabilities/device-io-controls.d.ts +4 -0
  61. package/dist/components/native-capabilities/device-io-controls.d.ts.map +1 -0
  62. package/dist/components/native-capabilities/device-io-controls.js +28 -0
  63. package/dist/components/native-capabilities/device-list.d.ts +20 -0
  64. package/dist/components/native-capabilities/device-list.d.ts.map +1 -0
  65. package/dist/components/native-capabilities/device-list.js +14 -0
  66. package/dist/components/native-capabilities/display-map.d.ts +23 -0
  67. package/dist/components/native-capabilities/display-map.d.ts.map +1 -0
  68. package/dist/components/native-capabilities/display-map.js +114 -0
  69. package/dist/components/native-capabilities/haptic-button.d.ts +26 -0
  70. package/dist/components/native-capabilities/haptic-button.d.ts.map +1 -0
  71. package/dist/components/native-capabilities/haptic-button.js +94 -0
  72. package/dist/components/native-capabilities/hid-panel.d.ts +40 -0
  73. package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -0
  74. package/dist/components/native-capabilities/hid-panel.js +373 -0
  75. package/dist/components/native-capabilities/index.d.ts +27 -0
  76. package/dist/components/native-capabilities/index.d.ts.map +1 -0
  77. package/dist/components/native-capabilities/index.js +26 -0
  78. package/dist/components/native-capabilities/live-indicator.d.ts +15 -0
  79. package/dist/components/native-capabilities/live-indicator.d.ts.map +1 -0
  80. package/dist/components/native-capabilities/live-indicator.js +26 -0
  81. package/dist/components/native-capabilities/local-auth-button.d.ts +33 -0
  82. package/dist/components/native-capabilities/local-auth-button.d.ts.map +1 -0
  83. package/dist/components/native-capabilities/local-auth-button.js +115 -0
  84. package/dist/components/native-capabilities/location-panel.d.ts +29 -0
  85. package/dist/components/native-capabilities/location-panel.d.ts.map +1 -0
  86. package/dist/components/native-capabilities/location-panel.js +146 -0
  87. package/dist/components/native-capabilities/microphone-meter.d.ts +35 -0
  88. package/dist/components/native-capabilities/microphone-meter.d.ts.map +1 -0
  89. package/dist/components/native-capabilities/microphone-meter.js +244 -0
  90. package/dist/components/native-capabilities/midi-monitor.d.ts +54 -0
  91. package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -0
  92. package/dist/components/native-capabilities/midi-monitor.js +534 -0
  93. package/dist/components/native-capabilities/native-capability-panel.d.ts +11 -0
  94. package/dist/components/native-capabilities/native-capability-panel.d.ts.map +1 -0
  95. package/dist/components/native-capabilities/native-capability-panel.js +28 -0
  96. package/dist/components/native-capabilities/notification-panel.d.ts +24 -0
  97. package/dist/components/native-capabilities/notification-panel.d.ts.map +1 -0
  98. package/dist/components/native-capabilities/notification-panel.js +124 -0
  99. package/dist/components/native-capabilities/power-blocker-controller.d.ts +19 -0
  100. package/dist/components/native-capabilities/power-blocker-controller.d.ts.map +1 -0
  101. package/dist/components/native-capabilities/power-blocker-controller.js +83 -0
  102. package/dist/components/native-capabilities/power-panel.d.ts +67 -0
  103. package/dist/components/native-capabilities/power-panel.d.ts.map +1 -0
  104. package/dist/components/native-capabilities/power-panel.js +309 -0
  105. package/dist/components/native-capabilities/readout.d.ts +10 -0
  106. package/dist/components/native-capabilities/readout.d.ts.map +1 -0
  107. package/dist/components/native-capabilities/readout.js +11 -0
  108. package/dist/components/native-capabilities/screen-share-preview.d.ts +36 -0
  109. package/dist/components/native-capabilities/screen-share-preview.d.ts.map +1 -0
  110. package/dist/components/native-capabilities/screen-share-preview.js +191 -0
  111. package/dist/components/native-capabilities/secure-storage-panel.d.ts +36 -0
  112. package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -0
  113. package/dist/components/native-capabilities/secure-storage-panel.js +193 -0
  114. package/dist/components/native-capabilities/serial-console.d.ts +64 -0
  115. package/dist/components/native-capabilities/serial-console.d.ts.map +1 -0
  116. package/dist/components/native-capabilities/serial-console.js +399 -0
  117. package/dist/components/native-capabilities/shortcut-recorder.d.ts +35 -0
  118. package/dist/components/native-capabilities/shortcut-recorder.d.ts.map +1 -0
  119. package/dist/components/native-capabilities/shortcut-recorder.js +217 -0
  120. package/dist/components/native-capabilities/stream-log.d.ts +35 -0
  121. package/dist/components/native-capabilities/stream-log.d.ts.map +1 -0
  122. package/dist/components/native-capabilities/stream-log.js +65 -0
  123. package/dist/components/native-capabilities/system-audio-monitor.d.ts +34 -0
  124. package/dist/components/native-capabilities/system-audio-monitor.d.ts.map +1 -0
  125. package/dist/components/native-capabilities/system-audio-monitor.js +275 -0
  126. package/dist/components/native-capabilities/usb-panel.d.ts +54 -0
  127. package/dist/components/native-capabilities/usb-panel.d.ts.map +1 -0
  128. package/dist/components/native-capabilities/usb-panel.js +363 -0
  129. package/dist/components/native-capabilities/use-capability.d.ts +20 -0
  130. package/dist/components/native-capabilities/use-capability.d.ts.map +1 -0
  131. package/dist/components/native-capabilities/use-capability.js +61 -0
  132. package/dist/components/ui/app-frame.d.ts +22 -0
  133. package/dist/components/ui/app-frame.d.ts.map +1 -0
  134. package/dist/components/ui/app-frame.js +56 -0
  135. package/dist/components/ui/button-group.d.ts +1 -1
  136. package/dist/components/ui/button.js +1 -1
  137. package/dist/components/ui/color-well.d.ts +13 -0
  138. package/dist/components/ui/color-well.d.ts.map +1 -0
  139. package/dist/components/ui/color-well.js +30 -0
  140. package/dist/components/ui/date-field.d.ts +19 -0
  141. package/dist/components/ui/date-field.d.ts.map +1 -0
  142. package/dist/components/ui/date-field.js +54 -0
  143. package/dist/components/ui/edge-fade.d.ts +11 -0
  144. package/dist/components/ui/edge-fade.d.ts.map +1 -0
  145. package/dist/components/ui/edge-fade.js +41 -0
  146. package/dist/components/ui/empty.js +1 -1
  147. package/dist/components/ui/field.d.ts +1 -1
  148. package/dist/components/ui/grid.d.ts +24 -0
  149. package/dist/components/ui/grid.d.ts.map +1 -0
  150. package/dist/components/ui/grid.js +234 -0
  151. package/dist/components/ui/icon-button.d.ts +15 -0
  152. package/dist/components/ui/icon-button.d.ts.map +1 -0
  153. package/dist/components/ui/icon-button.js +15 -0
  154. package/dist/components/ui/index.d.ts +19 -0
  155. package/dist/components/ui/index.d.ts.map +1 -1
  156. package/dist/components/ui/index.js +19 -0
  157. package/dist/components/ui/input-group.d.ts +1 -1
  158. package/dist/components/ui/inspector.d.ts +15 -0
  159. package/dist/components/ui/inspector.d.ts.map +1 -0
  160. package/dist/components/ui/inspector.js +26 -0
  161. package/dist/components/ui/kbd.d.ts +1 -1
  162. package/dist/components/ui/list.d.ts +24 -0
  163. package/dist/components/ui/list.d.ts.map +1 -0
  164. package/dist/components/ui/list.js +224 -0
  165. package/dist/components/ui/message-scroller-layout-stability.d.ts +33 -0
  166. package/dist/components/ui/message-scroller-layout-stability.d.ts.map +1 -0
  167. package/dist/components/ui/message-scroller-layout-stability.js +153 -0
  168. package/dist/components/ui/message-scroller.d.ts +11 -0
  169. package/dist/components/ui/message-scroller.d.ts.map +1 -0
  170. package/dist/components/ui/message-scroller.js +37 -0
  171. package/dist/components/ui/notification-dot.d.ts +4 -0
  172. package/dist/components/ui/notification-dot.d.ts.map +1 -0
  173. package/dist/components/ui/notification-dot.js +7 -0
  174. package/dist/components/ui/number-input.d.ts +16 -0
  175. package/dist/components/ui/number-input.d.ts.map +1 -0
  176. package/dist/components/ui/number-input.js +56 -0
  177. package/dist/components/ui/panel.d.ts +18 -0
  178. package/dist/components/ui/panel.d.ts.map +1 -0
  179. package/dist/components/ui/panel.js +40 -0
  180. package/dist/components/ui/popover.js +1 -1
  181. package/dist/components/ui/search-field.d.ts +19 -0
  182. package/dist/components/ui/search-field.d.ts.map +1 -0
  183. package/dist/components/ui/search-field.js +64 -0
  184. package/dist/components/ui/segmented-control.d.ts +21 -0
  185. package/dist/components/ui/segmented-control.d.ts.map +1 -0
  186. package/dist/components/ui/segmented-control.js +61 -0
  187. package/dist/components/ui/sidebar.js +1 -1
  188. package/dist/components/ui/sonner.d.ts +4 -3
  189. package/dist/components/ui/sonner.d.ts.map +1 -1
  190. package/dist/components/ui/sonner.js +7 -6
  191. package/dist/components/ui/split-view.d.ts +11 -0
  192. package/dist/components/ui/split-view.d.ts.map +1 -0
  193. package/dist/components/ui/split-view.js +13 -0
  194. package/dist/components/ui/status.d.ts +13 -0
  195. package/dist/components/ui/status.d.ts.map +1 -0
  196. package/dist/components/ui/status.js +36 -0
  197. package/dist/components/ui/table.d.ts +11 -2
  198. package/dist/components/ui/table.d.ts.map +1 -1
  199. package/dist/components/ui/table.js +28 -6
  200. package/dist/components/ui/text.d.ts +17 -0
  201. package/dist/components/ui/text.d.ts.map +1 -0
  202. package/dist/components/ui/text.js +55 -0
  203. package/dist/components/ui/toggle.js +1 -1
  204. package/dist/components/ui/toolbar.d.ts +20 -0
  205. package/dist/components/ui/toolbar.d.ts.map +1 -0
  206. package/dist/components/ui/toolbar.js +52 -0
  207. package/dist/index.d.ts +2 -2
  208. package/dist/index.d.ts.map +1 -1
  209. package/dist/index.js +4 -4
  210. package/dist/lib/frame-lifecycle.d.ts +28 -0
  211. package/dist/lib/frame-lifecycle.d.ts.map +1 -1
  212. package/dist/lib/frame-lifecycle.js +84 -0
  213. package/dist/lib/native-capabilities/access.d.ts +13 -0
  214. package/dist/lib/native-capabilities/access.d.ts.map +1 -0
  215. package/dist/lib/native-capabilities/access.js +53 -0
  216. package/dist/lib/native-capabilities/bluetooth-access.d.ts +14 -0
  217. package/dist/lib/native-capabilities/bluetooth-access.d.ts.map +1 -0
  218. package/dist/lib/native-capabilities/bluetooth-access.js +43 -0
  219. package/dist/lib/native-capabilities/bluetooth-connection.d.ts +19 -0
  220. package/dist/lib/native-capabilities/bluetooth-connection.d.ts.map +1 -0
  221. package/dist/lib/native-capabilities/bluetooth-connection.js +88 -0
  222. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +7 -0
  223. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts.map +1 -0
  224. package/dist/lib/native-capabilities/bluetooth-gatt.js +77 -0
  225. package/dist/lib/native-capabilities/bluetooth-internal.d.ts +10 -0
  226. package/dist/lib/native-capabilities/bluetooth-internal.d.ts.map +1 -0
  227. package/dist/lib/native-capabilities/bluetooth-internal.js +105 -0
  228. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +33 -0
  229. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts.map +1 -0
  230. package/dist/lib/native-capabilities/bluetooth-native-fallback.js +214 -0
  231. package/dist/lib/native-capabilities/bluetooth-types.d.ts +85 -0
  232. package/dist/lib/native-capabilities/bluetooth-types.d.ts.map +1 -0
  233. package/dist/lib/native-capabilities/bluetooth-types.js +2 -0
  234. package/dist/lib/native-capabilities/bluetooth.d.ts +7 -0
  235. package/dist/lib/native-capabilities/bluetooth.d.ts.map +1 -0
  236. package/dist/lib/native-capabilities/bluetooth.js +4 -0
  237. package/dist/lib/native-capabilities/bridge.d.ts +23 -0
  238. package/dist/lib/native-capabilities/bridge.d.ts.map +1 -0
  239. package/dist/lib/native-capabilities/bridge.js +266 -0
  240. package/dist/lib/native-capabilities/capabilities.d.ts +7 -0
  241. package/dist/lib/native-capabilities/capabilities.d.ts.map +1 -0
  242. package/dist/lib/native-capabilities/capabilities.js +95 -0
  243. package/dist/lib/native-capabilities/clipboard.d.ts +11 -0
  244. package/dist/lib/native-capabilities/clipboard.d.ts.map +1 -0
  245. package/dist/lib/native-capabilities/clipboard.js +58 -0
  246. package/dist/lib/native-capabilities/device-io-errors.d.ts +11 -0
  247. package/dist/lib/native-capabilities/device-io-errors.d.ts.map +1 -0
  248. package/dist/lib/native-capabilities/device-io-errors.js +82 -0
  249. package/dist/lib/native-capabilities/displays.d.ts +38 -0
  250. package/dist/lib/native-capabilities/displays.d.ts.map +1 -0
  251. package/dist/lib/native-capabilities/displays.js +12 -0
  252. package/dist/lib/native-capabilities/global-shortcuts.d.ts +86 -0
  253. package/dist/lib/native-capabilities/global-shortcuts.d.ts.map +1 -0
  254. package/dist/lib/native-capabilities/global-shortcuts.js +351 -0
  255. package/dist/lib/native-capabilities/haptics.d.ts +25 -0
  256. package/dist/lib/native-capabilities/haptics.d.ts.map +1 -0
  257. package/dist/lib/native-capabilities/haptics.js +18 -0
  258. package/dist/lib/native-capabilities/hid-native.d.ts +26 -0
  259. package/dist/lib/native-capabilities/hid-native.d.ts.map +1 -0
  260. package/dist/lib/native-capabilities/hid-native.js +229 -0
  261. package/dist/lib/native-capabilities/hid.d.ts +52 -0
  262. package/dist/lib/native-capabilities/hid.d.ts.map +1 -0
  263. package/dist/lib/native-capabilities/hid.js +163 -0
  264. package/dist/lib/native-capabilities/index.d.ts +40 -0
  265. package/dist/lib/native-capabilities/index.d.ts.map +1 -0
  266. package/dist/lib/native-capabilities/index.js +21 -0
  267. package/dist/lib/native-capabilities/local-authentication.d.ts +32 -0
  268. package/dist/lib/native-capabilities/local-authentication.d.ts.map +1 -0
  269. package/dist/lib/native-capabilities/local-authentication.js +46 -0
  270. package/dist/lib/native-capabilities/location.d.ts +49 -0
  271. package/dist/lib/native-capabilities/location.d.ts.map +1 -0
  272. package/dist/lib/native-capabilities/location.js +114 -0
  273. package/dist/lib/native-capabilities/media-permissions.d.ts +28 -0
  274. package/dist/lib/native-capabilities/media-permissions.d.ts.map +1 -0
  275. package/dist/lib/native-capabilities/media-permissions.js +37 -0
  276. package/dist/lib/native-capabilities/media.d.ts +17 -0
  277. package/dist/lib/native-capabilities/media.d.ts.map +1 -0
  278. package/dist/lib/native-capabilities/media.js +104 -0
  279. package/dist/lib/native-capabilities/midi-access.d.ts +13 -0
  280. package/dist/lib/native-capabilities/midi-access.d.ts.map +1 -0
  281. package/dist/lib/native-capabilities/midi-access.js +68 -0
  282. package/dist/lib/native-capabilities/midi-internal.d.ts +12 -0
  283. package/dist/lib/native-capabilities/midi-internal.d.ts.map +1 -0
  284. package/dist/lib/native-capabilities/midi-internal.js +88 -0
  285. package/dist/lib/native-capabilities/midi-native-fallback.d.ts +27 -0
  286. package/dist/lib/native-capabilities/midi-native-fallback.d.ts.map +1 -0
  287. package/dist/lib/native-capabilities/midi-native-fallback.js +127 -0
  288. package/dist/lib/native-capabilities/midi-ports.d.ts +6 -0
  289. package/dist/lib/native-capabilities/midi-ports.d.ts.map +1 -0
  290. package/dist/lib/native-capabilities/midi-ports.js +115 -0
  291. package/dist/lib/native-capabilities/midi-types.d.ts +25 -0
  292. package/dist/lib/native-capabilities/midi-types.d.ts.map +1 -0
  293. package/dist/lib/native-capabilities/midi-types.js +1 -0
  294. package/dist/lib/native-capabilities/midi.d.ts +6 -0
  295. package/dist/lib/native-capabilities/midi.d.ts.map +1 -0
  296. package/dist/lib/native-capabilities/midi.js +3 -0
  297. package/dist/lib/native-capabilities/native-device-io.d.ts +28 -0
  298. package/dist/lib/native-capabilities/native-device-io.d.ts.map +1 -0
  299. package/dist/lib/native-capabilities/native-device-io.js +91 -0
  300. package/dist/lib/native-capabilities/native-device-lifecycle.d.ts +13 -0
  301. package/dist/lib/native-capabilities/native-device-lifecycle.d.ts.map +1 -0
  302. package/dist/lib/native-capabilities/native-device-lifecycle.js +40 -0
  303. package/dist/lib/native-capabilities/notifications.d.ts +38 -0
  304. package/dist/lib/native-capabilities/notifications.d.ts.map +1 -0
  305. package/dist/lib/native-capabilities/notifications.js +50 -0
  306. package/dist/lib/native-capabilities/power-session.d.ts +113 -0
  307. package/dist/lib/native-capabilities/power-session.d.ts.map +1 -0
  308. package/dist/lib/native-capabilities/power-session.js +264 -0
  309. package/dist/lib/native-capabilities/secure-storage.d.ts +36 -0
  310. package/dist/lib/native-capabilities/secure-storage.d.ts.map +1 -0
  311. package/dist/lib/native-capabilities/secure-storage.js +64 -0
  312. package/dist/lib/native-capabilities/serial-native.d.ts +23 -0
  313. package/dist/lib/native-capabilities/serial-native.d.ts.map +1 -0
  314. package/dist/lib/native-capabilities/serial-native.js +181 -0
  315. package/dist/lib/native-capabilities/serial.d.ts +76 -0
  316. package/dist/lib/native-capabilities/serial.d.ts.map +1 -0
  317. package/dist/lib/native-capabilities/serial.js +215 -0
  318. package/dist/lib/native-capabilities/system-audio.d.ts +127 -0
  319. package/dist/lib/native-capabilities/system-audio.d.ts.map +1 -0
  320. package/dist/lib/native-capabilities/system-audio.js +330 -0
  321. package/dist/lib/native-capabilities/types.d.ts +62 -0
  322. package/dist/lib/native-capabilities/types.d.ts.map +1 -0
  323. package/dist/lib/native-capabilities/types.js +27 -0
  324. package/dist/lib/native-capabilities/usb-native.d.ts +39 -0
  325. package/dist/lib/native-capabilities/usb-native.d.ts.map +1 -0
  326. package/dist/lib/native-capabilities/usb-native.js +217 -0
  327. package/dist/lib/native-capabilities/usb.d.ts +85 -0
  328. package/dist/lib/native-capabilities/usb.d.ts.map +1 -0
  329. package/dist/lib/native-capabilities/usb.js +225 -0
  330. package/docs/README.md +37 -0
  331. package/docs/accessibility.md +32 -0
  332. package/docs/app-anatomy.md +72 -0
  333. package/docs/component-catalog.md +59 -0
  334. package/docs/component-guide-template.md +37 -0
  335. package/docs/design-tokens.md +172 -0
  336. package/docs/foundations.md +56 -0
  337. package/docs/native-integration.md +33 -0
  338. package/docs/standalone-app-windows.md +128 -0
  339. package/package.json +9 -3
  340. package/src/components/ui/alert.md +55 -0
  341. package/src/components/ui/app-frame.md +33 -0
  342. package/src/components/ui/badge.md +57 -0
  343. package/src/components/ui/button.md +76 -0
  344. package/src/components/ui/color-well.md +11 -0
  345. package/src/components/ui/combobox.md +43 -0
  346. package/src/components/ui/date-field.md +32 -0
  347. package/src/components/ui/edge-fade.md +7 -0
  348. package/src/components/ui/empty.md +82 -0
  349. package/src/components/ui/field.md +77 -0
  350. package/src/components/ui/grid.md +105 -0
  351. package/src/components/ui/icon-button.md +36 -0
  352. package/src/components/ui/inspector.md +11 -0
  353. package/src/components/ui/item.md +87 -0
  354. package/src/components/ui/list.md +107 -0
  355. package/src/components/ui/notification-dot.md +7 -0
  356. package/src/components/ui/number-input.md +19 -0
  357. package/src/components/ui/panel.md +11 -0
  358. package/src/components/ui/resizable.md +66 -0
  359. package/src/components/ui/scroll-area.md +68 -0
  360. package/src/components/ui/search-field.md +33 -0
  361. package/src/components/ui/segmented-control.md +39 -0
  362. package/src/components/ui/sidebar.md +113 -0
  363. package/src/components/ui/sonner.md +37 -0
  364. package/src/components/ui/split-view.md +15 -0
  365. package/src/components/ui/status.md +12 -0
  366. package/src/components/ui/table.md +35 -0
  367. package/src/components/ui/tabs.md +66 -0
  368. package/src/components/ui/text.md +17 -0
  369. package/src/components/ui/toggle-group.md +80 -0
  370. package/src/components/ui/toggle.md +73 -0
  371. package/src/components/ui/toolbar.md +21 -0
  372. package/src/styles/index.css +491 -3
@@ -1,15 +1,17 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { AlertCircle, ArrowDown, ChevronDown, ClipboardList, Code2, CornerDownRight, ExternalLink, GripVertical, Image as ImageIcon, ListPlus, Pencil, Trash2, } from 'lucide-react';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { AlertCircle, ChevronDown, ClipboardList, Code2, CornerDownRight, GripVertical, Image as ImageIcon, ListPlus, Loader2, Maximize2, Minimize2, Pencil, RotateCcw, Trash2, } from 'lucide-react';
4
4
  import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
5
5
  import { cn } from '../../lib/utils';
6
6
  import { Button } from '../ui/button';
7
- import { ScrollArea } from '../ui/scroll-area';
7
+ import { Dialog, DialogContent, DialogTitle } from '../ui/dialog';
8
+ import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, useMessageScroller, useMessageScrollerVisibility, } from '../ui/message-scroller';
9
+ import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
8
10
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '../ui/tooltip';
9
11
  import { ChatInput, } from './chat-input';
10
- import { CompactingMessage, ThinkingMessage, } from './chat-message';
12
+ import { CompactingMessage, ThinkingMessage, getChatMessageRenderKey, } from './chat-message';
11
13
  import { MessageRow, computeIsThinking, } from './chat-messages';
12
- import { ConversationHistory, } from './conversation-history';
14
+ import { ConversationHistory, ConversationSidebar, } from './conversation-history';
13
15
  import { ModelEffortSelector, } from './model-effort-selector';
14
16
  import { ToolApprovalProvider, } from './tool-approval-context';
15
17
  import { ToolProgressProvider } from './tool-progress-context';
@@ -17,7 +19,6 @@ import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, us
17
19
  import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
18
20
  import { CSS } from '@dnd-kit/utilities';
19
21
  import { AnimatePresence, motion } from 'framer-motion';
20
- import { Virtualizer } from 'virtua';
21
22
  const CODEX_OAUTH_ERROR_PATTERNS = [
22
23
  'codex oauth',
23
24
  'codex-oauth',
@@ -34,18 +35,26 @@ const MISSING_API_KEY_ERROR_PATTERNS = [
34
35
  'credential required in vault',
35
36
  'credential not configured in vault',
36
37
  ];
38
+ function isToastInteractionTarget(target) {
39
+ return (target instanceof Element &&
40
+ target.closest('[data-sonner-toaster], [data-sonner-toast]') !== null);
41
+ }
37
42
  const AUTH_PROMPT_COPY = {
38
43
  'missing-api-key': {
39
- title: 'API key required',
40
- description: 'Add an API key to Vault to start chatting with AI',
41
- action: 'Add API key',
44
+ label: 'Sign in with your ChatGPT account to chat with AI',
45
+ action: 'Connect ChatGPT',
42
46
  },
43
47
  'codex-oauth-expired': {
44
- title: 'Refresh OpenAI Codex auth',
45
- description: 'Open Settings > API Keys and reconnect OpenAI Codex to keep using Codex-backed OpenAI models.',
46
- action: 'Reconnect OpenAI Codex',
48
+ label: 'Sign in again to refresh your ChatGPT connection',
49
+ action: 'Reconnect ChatGPT',
47
50
  },
48
51
  };
52
+ export function getChatAuthPromptCopy(issue) {
53
+ return AUTH_PROMPT_COPY[issue];
54
+ }
55
+ function ChatAuthPrompt({ copy, isConnecting, onConnect, onAdvancedSetup, }) {
56
+ return (_jsxs("div", { className: "flex flex-col items-center gap-2 py-3 text-center", "data-chat-auth-prompt": true, children: [_jsx("p", { className: "text-muted-foreground max-w-sm text-sm", children: copy.label }), onConnect && (_jsx(Button, { onClick: onConnect, size: "sm", className: "cursor-pointer", disabled: isConnecting, children: isConnecting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 size-4 animate-spin" }), "Waiting for ChatGPT..."] })) : (copy.action) })), onAdvancedSetup && (_jsx(Button, { variant: "ghost", size: "sm", className: "text-muted-foreground hover:text-foreground h-auto cursor-pointer px-2 py-1 text-xs font-normal", onClick: onAdvancedSetup, disabled: isConnecting, children: "Advanced setup" }))] }));
57
+ }
49
58
  function messageIncludesAny(message, patterns) {
50
59
  const normalized = message.toLowerCase();
51
60
  return patterns.some((pattern) => normalized.includes(pattern));
@@ -64,6 +73,85 @@ export function resolveChatAuthIssue({ missingApiKey, authIssue, error, }) {
64
73
  }
65
74
  return null;
66
75
  }
76
+ export function hasPersistedChatError(messages) {
77
+ const lastMessage = messages.at(-1);
78
+ return Boolean(lastMessage?.parts?.some((part) => part.type === 'error'));
79
+ }
80
+ export function getPrependPreservedScrollTop(previousScrollTop, previousScrollHeight, nextScrollHeight) {
81
+ return (previousScrollTop + Math.max(0, nextScrollHeight - previousScrollHeight));
82
+ }
83
+ function MessageScrollerCommandSync({ signal }) {
84
+ const { scrollToEnd } = useMessageScroller();
85
+ const previousSignalRef = useRef(signal);
86
+ useEffect(() => {
87
+ if (previousSignalRef.current === signal)
88
+ return;
89
+ previousSignalRef.current = signal;
90
+ scrollToEnd({ behavior: 'auto' });
91
+ }, [scrollToEnd, signal]);
92
+ return null;
93
+ }
94
+ function getNavigationLabel(message) {
95
+ const text = message.content ??
96
+ message.parts
97
+ ?.flatMap((part) => (part.type === 'text' ? [part.text] : []))
98
+ .join(' ');
99
+ const normalized = text?.replace(/\s+/g, ' ').trim() || 'User message';
100
+ return normalized.length > 56 ? `${normalized.slice(0, 53)}...` : normalized;
101
+ }
102
+ function MessageNavigationTrail({ items }) {
103
+ const { scrollToMessage } = useMessageScroller();
104
+ const { currentAnchorId } = useMessageScrollerVisibility();
105
+ const anchors = useMemo(() => items.flatMap((item) => item.kind === 'message' && item.message.role === 'user'
106
+ ? [{ id: item.key, label: getNavigationLabel(item.message) }]
107
+ : []), [items]);
108
+ if (anchors.length < 2)
109
+ return null;
110
+ return (_jsx("div", { "data-fullscreen-message-navigation": true, className: "absolute bottom-8 left-3 top-8 z-20 flex w-9 items-center", children: _jsx(TooltipProvider, { delayDuration: 250, children: _jsx("nav", { "aria-label": "Conversation turns", className: "flex max-h-full w-full flex-col items-start overflow-y-auto py-2 [scrollbar-width:none]", children: _jsx("div", { "data-message-navigation-list": true, className: "my-auto flex w-full shrink-0 flex-col items-start", children: anchors.map((anchor) => {
111
+ const isCurrent = anchor.id === currentAnchorId;
112
+ return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", "aria-current": isCurrent ? 'location' : undefined, "aria-label": `Jump to: ${anchor.label}`, onClick: () => scrollToMessage(anchor.id, {
113
+ align: 'start',
114
+ behavior: 'smooth',
115
+ scrollMargin: 64,
116
+ }), "data-message-navigation-row": true, className: "flex h-2.5 w-9 shrink-0 cursor-pointer items-center outline-none", children: _jsx("span", { className: "flex h-0.5 w-[30px] items-center", children: _jsx("span", { "data-message-navigation-marker": true, className: cn('bg-muted-foreground h-0.5 w-[26px] origin-left rounded-full opacity-40', isCurrent && 'bg-foreground opacity-60') }) }) }) }), _jsx(TooltipContent, { side: "right", className: "max-w-72", children: anchor.label })] }, anchor.id));
117
+ }) }) }) }) }));
118
+ }
119
+ function ChatMessageViewport({ items, renderItem, toolProgress, onApprovalResponse, currentConversationId, scrollToBottomSignal, isBusy, hasOlderMessages = false, isLoadingOlderMessages = false, onLoadOlderMessages, showNavigationTrail = false, scrollAreaClassName, contentClassName, scrollButtonClassName, }) {
120
+ const viewportRef = useRef(null);
121
+ const loadingOlderRef = useRef(false);
122
+ const handleViewportScroll = useCallback((event) => {
123
+ const viewport = event.currentTarget;
124
+ if (viewport.scrollTop > 64 ||
125
+ !hasOlderMessages ||
126
+ isLoadingOlderMessages ||
127
+ loadingOlderRef.current ||
128
+ !onLoadOlderMessages) {
129
+ return;
130
+ }
131
+ loadingOlderRef.current = true;
132
+ const previousScrollHeight = viewport.scrollHeight;
133
+ const previousScrollTop = viewport.scrollTop;
134
+ void onLoadOlderMessages()
135
+ .then((outcome) => {
136
+ window.requestAnimationFrame(() => {
137
+ if (viewportRef.current !== viewport)
138
+ return;
139
+ if (outcome === 'reset') {
140
+ viewport.scrollTop = viewport.scrollHeight;
141
+ }
142
+ else if (outcome === 'prepended') {
143
+ viewport.scrollTop = getPrependPreservedScrollTop(previousScrollTop, previousScrollHeight, viewport.scrollHeight);
144
+ }
145
+ });
146
+ })
147
+ .finally(() => {
148
+ window.requestAnimationFrame(() => {
149
+ loadingOlderRef.current = false;
150
+ });
151
+ });
152
+ }, [hasOlderMessages, isLoadingOlderMessages, onLoadOlderMessages]);
153
+ return (_jsx(MessageScrollerProvider, { autoScroll: true, defaultScrollPosition: "end", scrollPreviousItemPeek: 64, children: _jsxs(MessageScroller, { className: "relative min-h-0 min-w-0 flex-1", children: [_jsx(MessageScrollerCommandSync, { signal: scrollToBottomSignal }), _jsx(MessageScrollerViewport, { ref: viewportRef, className: scrollAreaClassName, "data-message-scroll-fade": true, "data-has-older-messages": hasOlderMessages ? 'true' : 'false', onScroll: handleViewportScroll, children: _jsx(MessageScrollerContent, { "aria-busy": isBusy || isLoadingOlderMessages, className: contentClassName, children: _jsx(ToolProgressProvider, { value: toolProgress, children: _jsx(ToolApprovalProvider, { onApprovalResponse: onApprovalResponse ?? null, children: items.map((item) => (_jsx(MessageScrollerItem, { messageId: item.key, scrollAnchor: item.kind === 'message' && item.message.role === 'user', children: renderItem(item) }, item.key))) }) }) }) }), items.length > 0 && (_jsx(MessageScrollerButton, { className: scrollButtonClassName })), showNavigationTrail && _jsx(MessageNavigationTrail, { items: items })] }) }, currentConversationId ?? 'new-conversation'));
154
+ }
67
155
  function clampPercent(value) {
68
156
  if (!Number.isFinite(value))
69
157
  return 0;
@@ -77,7 +165,16 @@ function formatTokenCount(tokens) {
77
165
  const millions = tokens / 1_000_000;
78
166
  return `${Number.isInteger(millions) ? millions.toFixed(0) : millions.toFixed(2)}M`;
79
167
  }
80
- function ContextWindowIndicator({ usage }) {
168
+ function formatUsageReset(resetAt) {
169
+ if (!resetAt)
170
+ return null;
171
+ return new Intl.DateTimeFormat(undefined, {
172
+ weekday: 'short',
173
+ hour: 'numeric',
174
+ minute: '2-digit',
175
+ }).format(new Date(resetAt * 1_000));
176
+ }
177
+ function ContextWindowIndicator({ usage, planUsage, }) {
81
178
  if (!usage || usage.maxTokens <= 0)
82
179
  return null;
83
180
  const usedPercent = clampPercent(Math.round((usage.usedTokens / usage.maxTokens) * 100));
@@ -86,9 +183,15 @@ function ContextWindowIndicator({ usage }) {
86
183
  : usedPercent >= 75
87
184
  ? 'var(--warning)'
88
185
  : 'var(--muted-foreground)';
89
- return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring flex size-8 cursor-pointer items-center justify-center rounded-full bg-transparent p-0 focus-visible:outline-none focus-visible:ring-2", "aria-label": `Context window ${usedPercent}% full`, children: _jsx("span", { className: "relative size-4 rounded-full", style: {
186
+ return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground focus-visible:ring-ring flex size-8 cursor-pointer items-center justify-center rounded-full bg-transparent p-0 focus-visible:outline-none focus-visible:ring-2", "aria-label": `Context window ${usedPercent}% full`, children: _jsx("span", { className: "relative size-4 rounded-full", style: {
90
187
  background: `conic-gradient(${ringColor} ${usedPercent}%, color-mix(in oklch, var(--muted-foreground) 22%, transparent) 0)`,
91
- }, children: _jsx("span", { className: "bg-background absolute inset-[3px] rounded-full" }) }) }) }), _jsxs(TooltipContent, { align: "end", side: "top", sideOffset: 8, className: "w-56 px-3 py-2.5 text-center shadow-lg", children: [_jsx("div", { className: "opacity-70", children: "Context window:" }), _jsxs("div", { className: "mt-1 text-sm font-medium", children: [usedPercent, "% full"] }), _jsxs("div", { className: "mt-1 text-xs", children: [formatTokenCount(usage.usedTokens), " /", ' ', formatTokenCount(usage.maxTokens), " tokens used"] }), usage.compactsAutomatically && (_jsx("div", { className: "mt-2.5 text-xs font-medium leading-4", children: "Moldable automatically compacts its context" }))] })] }));
188
+ }, children: _jsx("span", { className: "bg-background absolute inset-[3px] rounded-full" }) }) }) }), _jsxs(PopoverContent, { align: "end", side: "top", sideOffset: 8, className: "w-80 p-3 shadow-lg", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Context window" }), _jsxs("span", { children: [formatTokenCount(usage.usedTokens), " /", ' ', formatTokenCount(usage.maxTokens), " (", usedPercent, "%)"] })] }), _jsx("div", { className: "bg-muted mt-2 h-1.5 overflow-hidden rounded-full", children: _jsx("div", { className: "bg-primary h-full rounded-full", style: { width: `${usedPercent}%` } }) }), usage.compactsAutomatically && (_jsx("div", { className: "text-muted-foreground mt-2 text-[11px] leading-4", children: "Moldable automatically compacts its context" })), planUsage && planUsage.windows.length > 0 && (_jsxs("div", { className: "border-border mt-3 flex flex-col gap-3 border-t pt-3", children: [_jsxs("div", { children: [_jsxs("div", { className: "text-muted-foreground text-xs", children: ["Plan usage limits", planUsage.planLabel ? ` · ${planUsage.planLabel}` : ''] }), planUsage.accountLabel && (_jsx("div", { className: "mt-0.5 truncate text-xs font-medium", children: planUsage.accountLabel }))] }), planUsage.windows.map((window) => {
189
+ const reset = formatUsageReset(window.resetAt);
190
+ const percent = clampPercent(window.usedPercent);
191
+ return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-xs", children: [_jsx("span", { children: window.label }), _jsxs("span", { className: "text-muted-foreground", children: [reset ? `Resets ${reset} · ` : '', percent, "%"] })] }), _jsx("div", { className: "bg-muted h-1.5 overflow-hidden rounded-full", children: _jsx("div", { className: percent >= 90
192
+ ? 'bg-destructive h-full rounded-full'
193
+ : 'bg-primary h-full rounded-full', style: { width: `${percent}%` } }) })] }, window.label));
194
+ })] }))] })] }));
92
195
  }
93
196
  function ContextCompactedDivider() {
94
197
  return (_jsx("div", { "data-testid": "context-compacted-divider", className: "text-muted-foreground/80 w-full px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "bg-border h-px min-w-8 flex-1" }), _jsxs("div", { className: "flex select-none items-center gap-2 whitespace-nowrap text-[13px] font-medium leading-5", children: [_jsx(ClipboardList, { className: "size-4" }), _jsx("span", { children: "Context automatically compacted" })] }), _jsx("div", { className: "bg-border h-px min-w-8 flex-1" })] }) }));
@@ -118,19 +221,10 @@ function QueuedMessageRow({ message, isResponding, onRetryQueuedMessage, onSteer
118
221
  /**
119
222
  * Floating chat panel with model selector
120
223
  */
121
- export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, modelProviders, modelEffortPresets, selectedModel, selectedReasoningEffort, onModelEffortChange, conversations, currentConversationId, scrollToBottomSignal = 0, onSelectConversation, onDeleteConversation, placeholder = 'Ask anything...', welcomeMessage, isExpanded, onExpandedChange, isMinimized = false, onMinimizedChange, className, error, missingApiKey, authIssue, onAddApiKey, toolProgress = {}, onApprovalResponse, isEditingApp = true, onEditingAppChange, showEditingAppToggle = false, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments = [], onRemoveImageAttachment, isImageDropActive = false, queuedMessages = [], onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting = false, compactedHistoryStartIndex, contextUsage, }) {
224
+ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChange, onSubmit, onStop, onNewChat, modelProviders, modelEffortPresets, selectedModel, selectedReasoningEffort, onModelEffortChange, conversations, currentConversationId, currentAppId, hasMoreConversations = false, isLoadingMoreConversations = false, onLoadMoreConversations, onResolveMessageContent, scrollToBottomSignal = 0, hasOlderMessages = false, isLoadingOlderMessages = false, onLoadOlderMessages, onSelectConversation, onArchiveConversation, onArchiveConversationGroup, placeholder = 'Ask anything...', welcomeMessage, isExpanded, onExpandedChange, isFullScreen = false, onFullScreenChange, isMinimized = false, onMinimizedChange, className, error, onRetryError, missingApiKey, authIssue, onConnectChatGPT, onAdvancedSetup, toolProgress = {}, onApprovalResponse, isEditingApp = true, onEditingAppChange, showEditingAppToggle = false, checkpoints, restoringMessageId, onRestoreCheckpoint, imageAttachments = [], onRemoveImageAttachment, isImageDropActive = false, queuedMessages = [], onRemoveQueuedMessage, onRetryQueuedMessage, onSteerQueuedMessage, onReorderQueuedMessages, onEditQueuedMessage, slashCommands, onSlashCommandSelect, isCompacting = false, compactedHistoryStartIndex, contextUsage, planUsage, }) {
122
225
  const inputRef = useRef(null);
123
- const scrollAreaRef = useRef(null);
124
- const viewportRef = useRef(null);
125
- const virtualizerRef = useRef(null);
126
- const prevMessageCountRef = useRef(messages.length);
127
- const prevConversationIdRef = useRef(currentConversationId ?? null);
128
- const prevScrollToBottomSignalRef = useRef(scrollToBottomSignal);
129
- const pendingConversationScrollIdRef = useRef(null);
130
- const hasPendingScrollToBottomSignalRef = useRef(false);
131
- const scrollRafRef = useRef(null);
132
- const [viewportVersion, setViewportVersion] = useState(0);
133
- const [isAtBottom, setIsAtBottom] = useState(true);
226
+ const fullScreenTriggerRef = useRef(null);
227
+ const [isConnectingChatGPT, setIsConnectingChatGPT] = useState(false);
134
228
  const queuedMessageIds = useMemo(() => queuedMessages.map((message) => message.id), [queuedMessages]);
135
229
  const queueSensors = useSensors(useSensor(PointerSensor, {
136
230
  activationConstraint: {
@@ -141,59 +235,31 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
141
235
  }));
142
236
  const isResponding = status === 'streaming' || status === 'submitted';
143
237
  const controlsDisabled = isTurnInFlight ?? isResponding;
144
- const composerControls = (_jsxs(_Fragment, { children: [_jsx(ContextWindowIndicator, { usage: contextUsage }), modelProviders.length > 0 && modelEffortPresets.length > 0 ? (_jsx(ModelEffortSelector, { providers: modelProviders, presets: modelEffortPresets, selectedModel: selectedModel, selectedReasoningEffort: selectedReasoningEffort, onSelectionChange: onModelEffortChange, disabled: controlsDisabled })) : null] }));
145
- // Capture the Radix viewport element so virtua can use it as the scroll container
146
- useEffect(() => {
147
- const scrollArea = scrollAreaRef.current;
148
- if (!scrollArea)
149
- return;
150
- const viewport = scrollArea.querySelector('[data-radix-scroll-area-viewport]');
151
- if (!viewport)
152
- return;
153
- viewport.style.overflowAnchor = 'none';
154
- if (viewportRef.current !== viewport) {
155
- viewportRef.current = viewport;
156
- setViewportVersion((version) => version + 1);
157
- }
158
- }, [isExpanded]);
159
- // Track scroll position to detect if user is at bottom
160
- useEffect(() => {
161
- const viewport = viewportRef.current;
162
- if (!viewport)
163
- return;
164
- const handleScroll = () => {
165
- const { scrollTop, scrollHeight, clientHeight } = viewport;
166
- // Consider "at bottom" if within 50px of the bottom
167
- const atBottom = scrollHeight - scrollTop - clientHeight < 50;
168
- setIsAtBottom(atBottom);
169
- };
170
- handleScroll();
171
- viewport.addEventListener('scroll', handleScroll);
172
- return () => viewport.removeEventListener('scroll', handleScroll);
173
- }, [viewportVersion]);
238
+ const isChatOpen = isExpanded || isFullScreen;
239
+ const composerControls = (_jsxs(_Fragment, { children: [_jsx(ContextWindowIndicator, { usage: contextUsage, planUsage: planUsage }), modelProviders.length > 0 && modelEffortPresets.length > 0 ? (_jsx(ModelEffortSelector, { providers: modelProviders, presets: modelEffortPresets, selectedModel: selectedModel, selectedReasoningEffort: selectedReasoningEffort, onSelectionChange: onModelEffortChange, disabled: controlsDisabled })) : null] }));
174
240
  // Focus input when expanded
175
241
  useEffect(() => {
176
- if (isExpanded) {
242
+ if (isChatOpen) {
177
243
  const timer = setTimeout(() => {
178
244
  inputRef.current?.focus();
179
245
  }, 200);
180
246
  return () => clearTimeout(timer);
181
247
  }
182
- }, [isExpanded]);
248
+ }, [isChatOpen]);
183
249
  const resolvedAuthIssue = resolveChatAuthIssue({
184
250
  missingApiKey,
185
251
  authIssue,
186
252
  error,
187
253
  });
188
254
  const authPromptCopy = resolvedAuthIssue
189
- ? AUTH_PROMPT_COPY[resolvedAuthIssue]
255
+ ? getChatAuthPromptCopy(resolvedAuthIssue)
190
256
  : null;
191
257
  const showAuthPrompt = Boolean(resolvedAuthIssue);
192
258
  const submitDisabled = showAuthPrompt;
193
259
  const handleSubmit = useCallback((e, mode) => {
194
260
  e?.preventDefault();
195
261
  if (submitDisabled) {
196
- if (!isExpanded) {
262
+ if (!isChatOpen) {
197
263
  onExpandedChange(true);
198
264
  }
199
265
  return;
@@ -201,17 +267,15 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
201
267
  if (!input.trim() && imageAttachments.length === 0)
202
268
  return;
203
269
  const submitMode = mode ?? (isResponding ? 'queue' : 'send');
204
- if (!isExpanded) {
270
+ if (!isChatOpen) {
205
271
  onExpandedChange(true);
206
272
  }
207
- // Reset to bottom when user sends a message
208
- setIsAtBottom(true);
209
273
  onSubmit(e, submitMode);
210
274
  }, [
211
275
  imageAttachments.length,
212
276
  input,
213
277
  isResponding,
214
- isExpanded,
278
+ isChatOpen,
215
279
  onExpandedChange,
216
280
  onSubmit,
217
281
  submitDisabled,
@@ -224,50 +288,79 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
224
288
  }, [onReorderQueuedMessages]);
225
289
  const handleEditQueuedMessage = useCallback((id) => {
226
290
  onEditQueuedMessage?.(id);
227
- if (!isExpanded) {
291
+ if (!isChatOpen) {
228
292
  onExpandedChange(true);
229
293
  }
230
294
  window.setTimeout(() => inputRef.current?.focus(), 0);
231
- }, [isExpanded, onEditQueuedMessage, onExpandedChange]);
295
+ }, [isChatOpen, onEditQueuedMessage, onExpandedChange]);
232
296
  const handleNewChat = useCallback(() => {
233
297
  onNewChat?.();
234
298
  inputRef.current?.focus();
235
299
  }, [onNewChat]);
300
+ const handleConnectChatGPT = useCallback(async () => {
301
+ if (!onConnectChatGPT || isConnectingChatGPT)
302
+ return;
303
+ setIsConnectingChatGPT(true);
304
+ try {
305
+ await onConnectChatGPT();
306
+ }
307
+ catch (error) {
308
+ console.error('Failed to connect ChatGPT:', error);
309
+ }
310
+ finally {
311
+ setIsConnectingChatGPT(false);
312
+ }
313
+ }, [isConnectingChatGPT, onConnectChatGPT]);
314
+ const editingAppControl = showEditingAppToggle && onEditingAppChange ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: (event) => {
315
+ event.preventDefault();
316
+ onEditingAppChange(!isEditingApp);
317
+ }, className: cn('cursor-pointer', isEditingApp
318
+ ? 'text-primary bg-primary/10 hover:bg-primary/20'
319
+ : 'text-muted-foreground hover:text-foreground'), children: _jsx(Code2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx("p", { children: isEditingApp
320
+ ? 'Editing this app (click to disable)'
321
+ : 'Not editing app (click to enable)' }) })] }) })) : null;
236
322
  const composerStartControls = (_jsxs(_Fragment, { children: [conversations &&
237
323
  (conversations.length > 0 || onNewChat) &&
238
- onSelectConversation && (_jsx(ConversationHistory, { conversations: conversations, currentConversationId: currentConversationId, onSelect: onSelectConversation, onDelete: onDeleteConversation, onNewChat: handleNewChat, newChatDisabled: controlsDisabled, disabled: controlsDisabled, dropdownAlign: "start", dropdownSide: "top", tooltipSide: "top" })), showEditingAppToggle && onEditingAppChange && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: (event) => {
239
- event.preventDefault();
240
- onEditingAppChange(!isEditingApp);
241
- }, className: cn('cursor-pointer', isEditingApp
242
- ? 'text-primary bg-primary/10 hover:bg-primary/20'
243
- : 'text-muted-foreground hover:text-foreground'), children: _jsx(Code2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: _jsx("p", { children: isEditingApp
244
- ? 'Editing this app (click to disable)'
245
- : 'Not editing app (click to enable)' }) })] }) }))] }));
324
+ onSelectConversation && (_jsx(ConversationHistory, { conversations: conversations, currentConversationId: currentConversationId, currentAppId: currentAppId, onSelect: onSelectConversation, onArchive: onArchiveConversation, onArchiveGroup: onArchiveConversationGroup, onNewChat: handleNewChat, newChatDisabled: false, disabled: false, dropdownAlign: "start", dropdownSide: "top", tooltipSide: "top", hasMoreConversations: hasMoreConversations, isLoadingMoreConversations: isLoadingMoreConversations, onLoadMoreConversations: onLoadMoreConversations })), editingAppControl] }));
246
325
  // Keyboard shortcut: Cmd+Shift+O for new chat
247
326
  useEffect(() => {
248
327
  const handleKeyDown = (e) => {
249
328
  if (e.key === 'o' && e.metaKey && e.shiftKey) {
250
329
  e.preventDefault();
251
330
  // Only create new chat if conversation controls are currently available.
252
- if (!controlsDisabled && isExpanded) {
331
+ if (isChatOpen) {
253
332
  handleNewChat();
254
333
  }
255
334
  }
256
335
  };
257
336
  document.addEventListener('keydown', handleKeyDown);
258
337
  return () => document.removeEventListener('keydown', handleKeyDown);
259
- }, [controlsDisabled, isExpanded, handleNewChat]);
338
+ }, [isChatOpen, handleNewChat]);
260
339
  // Handle minimize button - now goes to minimized state
261
340
  const handleMinimize = useCallback(() => {
341
+ if (isFullScreen) {
342
+ onFullScreenChange?.(false);
343
+ }
262
344
  if (isExpanded) {
263
345
  onExpandedChange(false);
264
346
  }
265
347
  onMinimizedChange?.(true);
266
- }, [isExpanded, onExpandedChange, onMinimizedChange]);
348
+ }, [
349
+ isExpanded,
350
+ isFullScreen,
351
+ onExpandedChange,
352
+ onFullScreenChange,
353
+ onMinimizedChange,
354
+ ]);
267
355
  const isStreaming = status === 'streaming' || status === 'submitted';
268
356
  const isThinking = useMemo(() => computeIsThinking(messages, status), [messages, status]);
269
- const showErrorMessage = Boolean(error) && status === 'error' && !showAuthPrompt;
270
- const lastMessageId = messages[messages.length - 1]?.id;
357
+ const showErrorMessage = Boolean(error) &&
358
+ status === 'error' &&
359
+ !showAuthPrompt &&
360
+ !hasPersistedChatError(messages);
361
+ const lastMessageKey = messages.length > 0
362
+ ? getChatMessageRenderKey(messages[messages.length - 1], messages.length - 1)
363
+ : null;
271
364
  const listItems = useMemo(() => {
272
365
  const items = [];
273
366
  if (messages.length === 0 && welcomeMessage) {
@@ -283,7 +376,11 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
283
376
  kind: 'context-compacted-divider',
284
377
  });
285
378
  }
286
- items.push({ key: message.id, kind: 'message', message });
379
+ items.push({
380
+ key: getChatMessageRenderKey(message, index),
381
+ kind: 'message',
382
+ message,
383
+ });
287
384
  }
288
385
  if (isThinking && !isCompacting) {
289
386
  items.push({ key: 'thinking', kind: 'thinking' });
@@ -291,9 +388,6 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
291
388
  if (isCompacting) {
292
389
  items.push({ key: 'compacting', kind: 'compacting' });
293
390
  }
294
- if (showAuthPrompt) {
295
- items.push({ key: 'auth-prompt', kind: 'auth-prompt' });
296
- }
297
391
  if (showErrorMessage) {
298
392
  items.push({ key: 'error', kind: 'error' });
299
393
  }
@@ -304,7 +398,6 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
304
398
  compactedHistoryStartIndex,
305
399
  messages,
306
400
  showErrorMessage,
307
- showAuthPrompt,
308
401
  welcomeMessage,
309
402
  ]);
310
403
  const renderVirtualItem = useCallback((item) => {
@@ -315,99 +408,43 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
315
408
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(ContextCompactedDivider, {}) }));
316
409
  case 'message': {
317
410
  const checkpoint = checkpoints?.get(item.message.id);
318
- return (_jsx("div", { className: "px-2 pb-3", children: _jsx(MessageRow, { message: item.message, isLast: item.message.id === lastMessageId, isStreaming: isStreaming, checkpoint: checkpoint, restoringMessageId: restoringMessageId, onRestoreCheckpoint: onRestoreCheckpoint }) }));
411
+ return (_jsx("div", { className: "px-2 pb-3", children: _jsx(MessageRow, { message: item.message, isLast: item.key === lastMessageKey, isStreaming: isStreaming, checkpoint: checkpoint, restoringMessageId: restoringMessageId, onRestoreCheckpoint: onRestoreCheckpoint, onResolveMessageContent: onResolveMessageContent, onRetryError: item.key === lastMessageKey ? onRetryError : undefined }) }));
319
412
  }
320
413
  case 'thinking':
321
414
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(ThinkingMessage, {}) }));
322
415
  case 'compacting':
323
416
  return (_jsx("div", { className: "px-2 pb-3", children: _jsx(CompactingMessage, {}) }));
324
- case 'auth-prompt':
325
- if (resolvedAuthIssue === 'codex-oauth-expired') {
326
- return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "bg-muted/30 mx-2 flex flex-col gap-3 rounded-lg p-4", children: [_jsx("div", { className: "flex items-start justify-between gap-3", children: _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: authPromptCopy?.title ?? 'Refresh OpenAI Codex auth' }), _jsx("p", { className: "text-muted-foreground text-xs", children: authPromptCopy?.description ??
327
- 'Open Settings > API Keys and reconnect OpenAI Codex.' })] }) }), onAddApiKey && (_jsxs(Button, { variant: "outline", className: "w-full cursor-pointer", onClick: onAddApiKey, children: [_jsx(ExternalLink, { className: "mr-2 size-4" }), authPromptCopy?.action ?? 'Reconnect OpenAI Codex'] }))] }) }));
328
- }
329
- return (_jsx("div", { className: "px-2 pb-4", children: _jsxs("div", { className: "border-primary/30 bg-primary/5 mx-2 flex flex-col items-center gap-3 rounded-lg border p-4 text-center", children: [_jsx("div", { className: "bg-primary/10 flex size-10 items-center justify-center rounded-full", children: _jsx(AlertCircle, { className: "text-primary size-5" }) }), _jsxs("div", { className: "max-w-sm", children: [_jsx("p", { className: "text-foreground font-medium", children: authPromptCopy?.title ?? 'Authentication required' }), _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: authPromptCopy?.description ??
330
- 'Open settings to configure chat authentication.' })] }), onAddApiKey && (_jsx(Button, { onClick: onAddApiKey, size: "sm", className: "cursor-pointer", children: authPromptCopy?.action ?? 'Open settings' }))] }) }));
331
417
  case 'error':
332
- return (_jsx("div", { className: "px-2 pb-4", children: error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 text-destructive mx-2 flex items-start gap-2 rounded-lg border p-3 text-sm", children: [_jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "font-medium", children: "Request failed" }), _jsx("p", { className: "text-destructive/80 mt-0.5 break-words", children: error.message || 'An unknown error occurred' })] })] })) }));
418
+ return (_jsx("div", { className: "px-2 pb-4", children: error && (_jsxs("div", { className: "border-destructive/30 bg-destructive/10 text-destructive mx-2 flex items-start gap-2 rounded-lg border p-3 text-sm", children: [_jsx(AlertCircle, { className: "mt-0.5 size-4 shrink-0" }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "font-medium", children: "Request failed" }), _jsx("p", { className: "text-destructive/80 mt-0.5 break-words", children: error.message || 'An unknown error occurred' }), onRetryError && (_jsxs("button", { type: "button", onClick: onRetryError, className: "border-destructive/30 hover:bg-destructive/10 mt-2 inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border px-2.5 text-xs font-medium transition-colors", children: [_jsx(RotateCcw, { className: "size-3.5" }), "Retry"] }))] })] })) }));
333
419
  }
334
420
  }, [
335
421
  checkpoints,
336
422
  error,
337
- authPromptCopy,
338
- resolvedAuthIssue,
339
423
  isStreaming,
340
- lastMessageId,
424
+ lastMessageKey,
341
425
  messages.length,
342
- onAddApiKey,
343
426
  onRestoreCheckpoint,
427
+ onResolveMessageContent,
428
+ onRetryError,
344
429
  restoringMessageId,
345
430
  welcomeMessage,
346
431
  ]);
347
- const scrollToBottom = useCallback((smooth = true) => {
348
- const lastIndex = listItems.length - 1;
349
- if (lastIndex < 0)
350
- return;
351
- if (scrollRafRef.current !== null) {
352
- cancelAnimationFrame(scrollRafRef.current);
353
- }
354
- setIsAtBottom(true);
355
- scrollRafRef.current = requestAnimationFrame(() => {
356
- virtualizerRef.current?.scrollToIndex(lastIndex, {
357
- align: 'end',
358
- smooth,
359
- });
360
- scrollRafRef.current = null;
361
- });
362
- }, [listItems.length]);
363
- // New conversations loaded from history should start at the latest message.
364
- useEffect(() => {
365
- const previousConversationId = prevConversationIdRef.current;
366
- const nextConversationId = currentConversationId ?? null;
367
- prevConversationIdRef.current = nextConversationId;
368
- if (previousConversationId !== nextConversationId) {
369
- pendingConversationScrollIdRef.current = nextConversationId;
370
- setIsAtBottom(true);
371
- }
372
- if (!nextConversationId ||
373
- pendingConversationScrollIdRef.current !== nextConversationId ||
374
- !isExpanded ||
375
- listItems.length === 0) {
376
- return;
377
- }
378
- scrollToBottom(false);
379
- pendingConversationScrollIdRef.current = null;
380
- }, [currentConversationId, isExpanded, listItems.length, scrollToBottom]);
381
- useEffect(() => {
382
- if (prevScrollToBottomSignalRef.current !== scrollToBottomSignal) {
383
- prevScrollToBottomSignalRef.current = scrollToBottomSignal;
384
- hasPendingScrollToBottomSignalRef.current = true;
385
- setIsAtBottom(true);
386
- }
387
- if (!hasPendingScrollToBottomSignalRef.current ||
388
- !isExpanded ||
389
- listItems.length === 0) {
390
- return;
391
- }
392
- scrollToBottom(false);
393
- hasPendingScrollToBottomSignalRef.current = false;
394
- }, [isExpanded, listItems.length, scrollToBottom, scrollToBottomSignal]);
395
- // Scroll to bottom on new messages if the user is already at bottom
396
- useEffect(() => {
397
- const previousMessageCount = prevMessageCountRef.current;
398
- const hasNewMessage = messages.length > previousMessageCount;
399
- prevMessageCountRef.current = messages.length;
400
- if (!isExpanded || !isAtBottom) {
401
- return;
402
- }
403
- scrollToBottom(hasNewMessage);
404
- return () => {
405
- if (scrollRafRef.current !== null) {
406
- cancelAnimationFrame(scrollRafRef.current);
407
- scrollRafRef.current = null;
408
- }
409
- };
410
- }, [isAtBottom, isExpanded, messages.length, scrollToBottom]);
432
+ if (isFullScreen && !isMinimized) {
433
+ const selectedConversation = conversations?.find((conversation) => conversation.id === currentConversationId);
434
+ return (_jsx(Dialog, { open: true, onOpenChange: () => undefined, children: _jsxs(DialogContent, { "data-moldable-chat-fullscreen": true, "data-chat-drop-target": true, showCloseButton: false, "aria-describedby": undefined, onInteractOutside: (event) => {
435
+ if (isToastInteractionTarget(event.target)) {
436
+ event.preventDefault();
437
+ }
438
+ }, onEscapeKeyDown: (event) => {
439
+ event.preventDefault();
440
+ onFullScreenChange?.(false);
441
+ }, onCloseAutoFocus: (event) => {
442
+ event.preventDefault();
443
+ window.requestAnimationFrame(() => {
444
+ fullScreenTriggerRef.current?.focus();
445
+ });
446
+ }, className: "bottom-1 left-1 right-1 top-1 z-50 flex h-auto w-auto max-w-none translate-x-0 translate-y-0 gap-0 overflow-hidden rounded-lg border-0 p-0 sm:max-w-none", children: [_jsx("div", { "data-tauri-drag-region": true, className: "absolute inset-x-0 top-0 z-20 h-9", "aria-hidden": "true" }), isImageDropActive && (_jsxs("div", { className: "bg-background/90 border-primary/50 text-foreground absolute inset-0 z-50 flex flex-col items-center justify-center gap-2 rounded-[inherit] border-2 border-dashed backdrop-blur-sm", children: [_jsx(ImageIcon, { className: "text-primary size-7" }), _jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-sm font-medium", children: "Drop images to attach" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "They stay on disk and are read when sent" })] })] })), _jsxs("aside", { className: "border-border bg-muted/50 relative z-10 flex w-[280px] shrink-0 flex-col overflow-hidden rounded-r-lg border-r px-3 pb-4 pt-11", children: [_jsxs("button", { type: "button", onClick: () => onFullScreenChange?.(false), className: "text-muted-foreground hover:text-foreground mb-4 flex h-8 cursor-pointer items-center gap-2 rounded-lg px-2 text-sm transition-colors", children: [_jsx(Minimize2, { className: "size-4" }), "Back to app"] }), _jsx(ConversationSidebar, { conversations: conversations ?? [], currentConversationId: currentConversationId, currentAppId: currentAppId, onSelect: onSelectConversation ?? (() => undefined), onArchive: onArchiveConversation, onArchiveGroup: onArchiveConversationGroup, onNewChat: handleNewChat, newChatDisabled: false, hideScrollbar: true, disabled: false, hasMoreConversations: hasMoreConversations, isLoadingMoreConversations: isLoadingMoreConversations, onLoadMoreConversations: onLoadMoreConversations, className: "min-h-0 flex-1" })] }), _jsxs("section", { className: "relative flex min-w-0 flex-1 flex-col", children: [_jsxs("header", { className: "border-border flex h-14 shrink-0 items-center justify-between border-b px-5", children: [_jsx(DialogTitle, { className: "truncate text-sm font-medium", children: selectedConversation?.title ?? 'New conversation' }), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => onFullScreenChange?.(false), "aria-label": "Exit full screen", className: "text-muted-foreground hover:text-foreground relative z-30 cursor-pointer", children: _jsx(Minimize2, { className: "size-4" }) }) }), _jsx(TooltipContent, { children: "Exit full screen" })] }) })] }), _jsx(ChatMessageViewport, { items: listItems, renderItem: renderVirtualItem, toolProgress: toolProgress, onApprovalResponse: onApprovalResponse, currentConversationId: currentConversationId, scrollToBottomSignal: scrollToBottomSignal, isBusy: isResponding, hasOlderMessages: hasOlderMessages, isLoadingOlderMessages: isLoadingOlderMessages, onLoadOlderMessages: onLoadOlderMessages, showNavigationTrail: true, contentClassName: "mx-auto w-full min-w-0 max-w-3xl overflow-hidden px-6 py-6", scrollButtonClassName: "absolute bottom-3 left-1/2 z-20 size-8 -translate-x-1/2 cursor-pointer rounded-full shadow-lg" }), authPromptCopy && (_jsx("div", { className: "mx-auto w-full max-w-3xl shrink-0 px-6 pb-2", children: _jsx(ChatAuthPrompt, { copy: authPromptCopy, isConnecting: isConnectingChatGPT, onConnect: onConnectChatGPT ? handleConnectChatGPT : undefined, onAdvancedSetup: onAdvancedSetup }) })), _jsxs("div", { className: "mx-auto w-full max-w-3xl shrink-0 px-6 pb-2", children: [queuedMessages.length > 0 && (_jsxs("div", { className: "border-border bg-muted/30 mb-2 rounded-xl border p-3", children: [_jsxs("div", { className: "text-muted-foreground mb-2 flex items-center gap-2 text-xs font-medium", children: [_jsx(ListPlus, { className: "size-3.5" }), _jsx("span", { children: "Queued follow-ups" })] }), _jsx(DndContext, { sensors: queueSensors, collisionDetection: closestCenter, onDragEnd: handleQueuedDragEnd, children: _jsx(SortableContext, { items: queuedMessageIds, strategy: verticalListSortingStrategy, children: _jsx("div", { className: "space-y-1.5", children: queuedMessages.map((message) => (_jsx(QueuedMessageRow, { message: message, isResponding: isResponding, onRetryQueuedMessage: onRetryQueuedMessage, onSteerQueuedMessage: onSteerQueuedMessage, onRemoveQueuedMessage: onRemoveQueuedMessage, onEditQueuedMessage: handleEditQueuedMessage }, message.id))) }) }) })] })), _jsx("div", { className: "bg-background overflow-hidden rounded-[24px] shadow-[0_8px_40px_-12px_rgba(0,0,0,0.2)]", children: _jsx(ChatInput, { input: input, onInputChange: onInputChange, onSubmit: handleSubmit, isResponding: isResponding, placeholder: placeholder, inputRef: inputRef, onStop: onStop, imageAttachments: imageAttachments, onRemoveImageAttachment: onRemoveImageAttachment, footerStartControls: editingAppControl, footerControls: composerControls, submitDisabled: submitDisabled, slashCommands: slashCommands, onSlashCommandSelect: onSlashCommandSelect }) })] })] })] }) }));
447
+ }
411
448
  return (_jsxs(_Fragment, { children: [_jsx(AnimatePresence, { children: isExpanded && !isMinimized && (_jsx(motion.div, { "data-moldable-chat-backdrop": true, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, className: "fixed inset-0 z-40 bg-black/20", onClick: () => onExpandedChange(false) })) }), _jsx(motion.div, { "data-moldable-chat-panel": true, initial: false, animate: {
412
449
  width: isExpanded ? 'min(90vw, 640px)' : '400px',
413
450
  y: isMinimized ? 'calc(100% + 24px)' : 0,
@@ -437,7 +474,7 @@ export function ChatPanel({ messages, status, isTurnInFlight, input, onInputChan
437
474
  } })), _jsxs("div", { className: "relative z-10 overflow-hidden rounded-[inherit]", children: [_jsxs(motion.div, { initial: false, animate: {
438
475
  height: isExpanded ? 'min(60vh, 480px)' : '0px',
439
476
  opacity: isExpanded ? 1 : 0,
440
- }, transition: { type: 'tween', duration: 0.2, ease: 'easeOut' }, className: "flex flex-col overflow-hidden", style: { pointerEvents: isExpanded ? 'auto' : 'none' }, children: [_jsx("div", { className: "absolute right-3 top-3 z-20", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: handleMinimize, className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(ChevronDown, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: _jsx("p", { children: "Minimize" }) })] }) }) }), _jsxs("div", { className: "relative min-h-0 min-w-0 flex-1", children: [_jsx(ScrollArea, { ref: scrollAreaRef, className: "h-full px-2", children: _jsx("div", { className: "min-w-0 max-w-full overflow-hidden py-4 pr-10", children: _jsx(ToolProgressProvider, { value: toolProgress, children: _jsx(ToolApprovalProvider, { onApprovalResponse: onApprovalResponse ?? null, children: viewportVersion > 0 ? (_jsx(Virtualizer, { ref: virtualizerRef, data: listItems, scrollRef: viewportRef, bufferSize: 300, children: (item) => renderVirtualItem(item) }, viewportVersion)) : (listItems.map((item) => (_jsx("div", { children: renderVirtualItem(item) }, item.key)))) }) }) }) }), !isAtBottom && listItems.length > 0 && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "secondary", size: "icon-sm", onClick: () => scrollToBottom(true), className: "absolute bottom-3 right-4 z-20 size-8 cursor-pointer rounded-full shadow-lg", children: _jsx(ArrowDown, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "top", children: "Scroll to bottom" })] }) }))] })] }), _jsxs("div", { className: "relative z-10", onClick: () => {
477
+ }, transition: { type: 'tween', duration: 0.2, ease: 'easeOut' }, className: "flex flex-col overflow-hidden", style: { pointerEvents: isExpanded ? 'auto' : 'none' }, children: [isExpanded && !isMinimized && (_jsxs("div", { className: "absolute right-2 top-2 z-20 grid grid-cols-1 gap-0.5", "data-moldable-chat-panel-controls": true, role: "toolbar", "aria-label": "Chat view controls", "aria-orientation": "vertical", children: [onFullScreenChange && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { ref: fullScreenTriggerRef, "data-moldable-chat-enter-fullscreen": true, variant: "ghost", size: "icon-sm", onClick: () => onFullScreenChange(true), "aria-label": "Enter full screen", className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(Maximize2, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: "Full screen" })] }) })), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: handleMinimize, className: "text-muted-foreground hover:text-foreground cursor-pointer", children: _jsx(ChevronDown, { className: "size-4" }) }) }), _jsx(TooltipContent, { side: "bottom", children: _jsx("p", { children: "Minimize" }) })] }) })] })), _jsx(ChatMessageViewport, { items: listItems, renderItem: renderVirtualItem, toolProgress: toolProgress, onApprovalResponse: onApprovalResponse, currentConversationId: currentConversationId, scrollToBottomSignal: scrollToBottomSignal, isBusy: isResponding, hasOlderMessages: hasOlderMessages, isLoadingOlderMessages: isLoadingOlderMessages, onLoadOlderMessages: onLoadOlderMessages, scrollAreaClassName: "px-2", contentClassName: "w-full min-w-0 max-w-full overflow-hidden py-4 pr-12", scrollButtonClassName: "absolute bottom-3 left-auto right-4 z-20 size-8 translate-x-0 cursor-pointer rounded-full shadow-lg" }), authPromptCopy && (_jsx("div", { className: "shrink-0 px-4 pb-2", children: _jsx(ChatAuthPrompt, { copy: authPromptCopy, isConnecting: isConnectingChatGPT, onConnect: onConnectChatGPT ? handleConnectChatGPT : undefined, onAdvancedSetup: onAdvancedSetup }) }))] }), _jsxs("div", { className: "relative z-10", onClick: () => {
441
478
  if (!isExpanded) {
442
479
  onExpandedChange(true);
443
480
  }