@moldable-ai/ui 0.2.22 → 0.2.24

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 (492) hide show
  1. package/dist/catalog/catalog-coverage.d.ts +1 -1
  2. package/dist/catalog/catalog-manifest.d.ts +1 -1
  3. package/dist/catalog/catalog-manifest.js +1 -1
  4. package/dist/catalog/component-catalog.d.ts +1 -1
  5. package/dist/catalog/component-catalog.js +2 -2
  6. package/dist/catalog/core-catalog-exclusions.d.ts +1 -1
  7. package/dist/catalog/core-catalog-exclusions.d.ts.map +1 -1
  8. package/dist/catalog/core-catalog-exclusions.js +1 -150
  9. package/dist/catalog/core-catalog.d.ts +1 -1
  10. package/dist/catalog/core-catalog.d.ts.map +1 -1
  11. package/dist/catalog/core-catalog.js +11 -7
  12. package/dist/catalog/core-collection-stories.d.ts +1 -1
  13. package/dist/catalog/core-collection-stories.d.ts.map +1 -1
  14. package/dist/catalog/core-collection-stories.js +40 -8
  15. package/dist/catalog/core-control-stories.d.ts +1 -1
  16. package/dist/catalog/core-control-stories.d.ts.map +1 -1
  17. package/dist/catalog/core-control-stories.js +48 -20
  18. package/dist/catalog/core-feedback-stories.d.ts +1 -1
  19. package/dist/catalog/core-feedback-stories.d.ts.map +1 -1
  20. package/dist/catalog/core-feedback-stories.js +89 -10
  21. package/dist/catalog/core-form-stories.d.ts +3 -0
  22. package/dist/catalog/core-form-stories.d.ts.map +1 -0
  23. package/dist/catalog/core-form-stories.js +56 -0
  24. package/dist/catalog/core-foundation-stories.d.ts +1 -1
  25. package/dist/catalog/core-foundation-stories.js +7 -7
  26. package/dist/catalog/core-layout-stories.d.ts +3 -0
  27. package/dist/catalog/core-layout-stories.d.ts.map +1 -0
  28. package/dist/catalog/core-layout-stories.js +78 -0
  29. package/dist/catalog/core-navigation-stories.d.ts +1 -1
  30. package/dist/catalog/core-navigation-stories.d.ts.map +1 -1
  31. package/dist/catalog/core-navigation-stories.js +25 -3
  32. package/dist/catalog/core-overlay-stories.d.ts +1 -1
  33. package/dist/catalog/core-overlay-stories.d.ts.map +1 -1
  34. package/dist/catalog/core-overlay-stories.js +113 -8
  35. package/dist/catalog/index.d.ts +6 -6
  36. package/dist/catalog/index.js +6 -6
  37. package/dist/components/app-error-boundary.js +2 -2
  38. package/dist/components/chat/chat-image-lightbox.js +3 -3
  39. package/dist/components/chat/chat-input.js +5 -5
  40. package/dist/components/chat/chat-message.js +17 -17
  41. package/dist/components/chat/chat-messages.d.ts +1 -1
  42. package/dist/components/chat/chat-messages.js +3 -3
  43. package/dist/components/chat/chat-panel.d.ts +6 -6
  44. package/dist/components/chat/chat-panel.d.ts.map +1 -1
  45. package/dist/components/chat/chat-panel.js +33 -33
  46. package/dist/components/chat/checkpoint-badge.js +3 -3
  47. package/dist/components/chat/conversation-history.d.ts.map +1 -1
  48. package/dist/components/chat/conversation-history.js +13 -13
  49. package/dist/components/chat/index.d.ts +20 -15
  50. package/dist/components/chat/index.d.ts.map +1 -1
  51. package/dist/components/chat/index.js +20 -15
  52. package/dist/components/chat/markdown.js +1 -1
  53. package/dist/components/chat/model-effort-selector.js +10 -10
  54. package/dist/components/chat/model-selector.js +4 -4
  55. package/dist/components/chat/reasoning-effort-selector.js +4 -4
  56. package/dist/components/chat/restore-dialog.js +3 -3
  57. package/dist/components/chat/thinking-timeline.js +2 -2
  58. package/dist/components/chat/tool-approval.d.ts +1 -1
  59. package/dist/components/chat/tool-approval.d.ts.map +1 -1
  60. package/dist/components/chat/tool-approval.js +9 -9
  61. package/dist/components/chat/tool-handlers.d.ts +2 -2
  62. package/dist/components/chat/tool-handlers.js +90 -90
  63. package/dist/components/chat/voice-orb-audio.d.ts +16 -0
  64. package/dist/components/chat/voice-orb-audio.d.ts.map +1 -0
  65. package/dist/components/chat/voice-orb-audio.js +110 -0
  66. package/dist/components/chat/voice-orb-renderer.d.ts +51 -0
  67. package/dist/components/chat/voice-orb-renderer.d.ts.map +1 -0
  68. package/dist/components/chat/voice-orb-renderer.js +410 -0
  69. package/dist/components/chat/voice-orb-shaders.d.ts +3 -0
  70. package/dist/components/chat/voice-orb-shaders.d.ts.map +1 -0
  71. package/dist/components/chat/voice-orb-shaders.js +355 -0
  72. package/dist/components/chat/voice-orb-types.d.ts +24 -0
  73. package/dist/components/chat/voice-orb-types.d.ts.map +1 -0
  74. package/dist/components/chat/voice-orb-types.js +73 -0
  75. package/dist/components/chat/voice-orb.d.ts +20 -0
  76. package/dist/components/chat/voice-orb.d.ts.map +1 -0
  77. package/dist/components/chat/voice-orb.js +67 -0
  78. package/dist/components/code-block.js +1 -1
  79. package/dist/components/hardware/bluetooth-panel.d.ts +2 -2
  80. package/dist/components/hardware/bluetooth-panel.js +10 -10
  81. package/dist/components/hardware/camera-preview.js +6 -6
  82. package/dist/components/hardware/capability-badge.d.ts +2 -2
  83. package/dist/components/hardware/capability-badge.js +2 -2
  84. package/dist/components/hardware/capability-matrix.d.ts +1 -1
  85. package/dist/components/hardware/capability-matrix.js +5 -5
  86. package/dist/components/hardware/clipboard-button.d.ts +1 -1
  87. package/dist/components/hardware/clipboard-button.js +2 -2
  88. package/dist/components/hardware/device-list.js +1 -1
  89. package/dist/components/hardware/display-map.d.ts +1 -1
  90. package/dist/components/hardware/display-map.js +7 -7
  91. package/dist/components/hardware/haptic-button.d.ts +2 -2
  92. package/dist/components/hardware/haptic-button.js +3 -3
  93. package/dist/components/hardware/hardware-panel.js +1 -1
  94. package/dist/components/hardware/hid-panel.d.ts +2 -2
  95. package/dist/components/hardware/hid-panel.js +10 -10
  96. package/dist/components/hardware/index.d.ts +26 -26
  97. package/dist/components/hardware/index.js +26 -26
  98. package/dist/components/hardware/live-indicator.js +1 -1
  99. package/dist/components/hardware/local-auth-button.d.ts +2 -2
  100. package/dist/components/hardware/local-auth-button.js +4 -4
  101. package/dist/components/hardware/location-panel.d.ts +1 -1
  102. package/dist/components/hardware/location-panel.js +6 -6
  103. package/dist/components/hardware/microphone-meter.js +7 -7
  104. package/dist/components/hardware/midi-monitor.d.ts +2 -2
  105. package/dist/components/hardware/midi-monitor.js +9 -9
  106. package/dist/components/hardware/notification-panel.d.ts +1 -1
  107. package/dist/components/hardware/notification-panel.js +8 -8
  108. package/dist/components/hardware/power-blocker-controller.d.ts +1 -1
  109. package/dist/components/hardware/power-blocker-controller.js +1 -1
  110. package/dist/components/hardware/power-panel.d.ts +1 -1
  111. package/dist/components/hardware/power-panel.js +9 -9
  112. package/dist/components/hardware/readout.js +1 -1
  113. package/dist/components/hardware/screen-share-preview.js +5 -5
  114. package/dist/components/hardware/secure-storage-panel.d.ts +1 -1
  115. package/dist/components/hardware/secure-storage-panel.js +9 -9
  116. package/dist/components/hardware/serial-console.d.ts +2 -2
  117. package/dist/components/hardware/serial-console.js +10 -10
  118. package/dist/components/hardware/shortcut-recorder.d.ts +1 -1
  119. package/dist/components/hardware/shortcut-recorder.js +4 -4
  120. package/dist/components/hardware/stream-log.js +1 -1
  121. package/dist/components/hardware/system-audio-monitor.d.ts +1 -1
  122. package/dist/components/hardware/system-audio-monitor.js +9 -9
  123. package/dist/components/hardware/usb-panel.d.ts +5 -5
  124. package/dist/components/hardware/usb-panel.js +10 -10
  125. package/dist/components/hardware/use-capability.d.ts +1 -1
  126. package/dist/components/hardware/use-capability.js +1 -1
  127. package/dist/components/markdown.js +5 -5
  128. package/dist/components/native-capabilities/bluetooth-panel.d.ts +2 -2
  129. package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -1
  130. package/dist/components/native-capabilities/bluetooth-panel.js +17 -17
  131. package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -1
  132. package/dist/components/native-capabilities/camera-preview.js +7 -7
  133. package/dist/components/native-capabilities/capability-badge.d.ts +2 -2
  134. package/dist/components/native-capabilities/capability-badge.js +4 -4
  135. package/dist/components/native-capabilities/capability-matrix.d.ts +1 -1
  136. package/dist/components/native-capabilities/capability-matrix.js +7 -7
  137. package/dist/components/native-capabilities/clipboard-button.d.ts +1 -1
  138. package/dist/components/native-capabilities/clipboard-button.js +2 -2
  139. package/dist/components/native-capabilities/device-list.js +4 -4
  140. package/dist/components/native-capabilities/display-map.d.ts +1 -1
  141. package/dist/components/native-capabilities/display-map.d.ts.map +1 -1
  142. package/dist/components/native-capabilities/display-map.js +11 -11
  143. package/dist/components/native-capabilities/haptic-button.d.ts +2 -2
  144. package/dist/components/native-capabilities/haptic-button.js +3 -3
  145. package/dist/components/native-capabilities/hid-panel.d.ts +2 -2
  146. package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -1
  147. package/dist/components/native-capabilities/hid-panel.js +14 -14
  148. package/dist/components/native-capabilities/index.d.ts +26 -26
  149. package/dist/components/native-capabilities/index.js +26 -26
  150. package/dist/components/native-capabilities/live-indicator.js +3 -3
  151. package/dist/components/native-capabilities/local-auth-button.d.ts +2 -2
  152. package/dist/components/native-capabilities/local-auth-button.js +4 -4
  153. package/dist/components/native-capabilities/location-panel.d.ts +1 -1
  154. package/dist/components/native-capabilities/location-panel.d.ts.map +1 -1
  155. package/dist/components/native-capabilities/location-panel.js +8 -8
  156. package/dist/components/native-capabilities/microphone-meter.js +9 -9
  157. package/dist/components/native-capabilities/midi-monitor.d.ts +2 -2
  158. package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -1
  159. package/dist/components/native-capabilities/midi-monitor.js +11 -11
  160. package/dist/components/native-capabilities/native-capability-panel.js +6 -6
  161. package/dist/components/native-capabilities/notification-panel.d.ts +1 -1
  162. package/dist/components/native-capabilities/notification-panel.js +9 -9
  163. package/dist/components/native-capabilities/power-blocker-controller.d.ts +1 -1
  164. package/dist/components/native-capabilities/power-blocker-controller.js +1 -1
  165. package/dist/components/native-capabilities/power-panel.d.ts +1 -1
  166. package/dist/components/native-capabilities/power-panel.d.ts.map +1 -1
  167. package/dist/components/native-capabilities/power-panel.js +12 -12
  168. package/dist/components/native-capabilities/readout.d.ts.map +1 -1
  169. package/dist/components/native-capabilities/readout.js +2 -2
  170. package/dist/components/native-capabilities/screen-share-preview.js +6 -6
  171. package/dist/components/native-capabilities/secure-storage-panel.d.ts +1 -1
  172. package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -1
  173. package/dist/components/native-capabilities/secure-storage-panel.js +11 -11
  174. package/dist/components/native-capabilities/serial-console.d.ts +2 -2
  175. package/dist/components/native-capabilities/serial-console.d.ts.map +1 -1
  176. package/dist/components/native-capabilities/serial-console.js +11 -11
  177. package/dist/components/native-capabilities/shortcut-recorder.d.ts +1 -1
  178. package/dist/components/native-capabilities/shortcut-recorder.js +5 -5
  179. package/dist/components/native-capabilities/stream-log.js +3 -3
  180. package/dist/components/native-capabilities/system-audio-monitor.d.ts +1 -1
  181. package/dist/components/native-capabilities/system-audio-monitor.js +12 -12
  182. package/dist/components/native-capabilities/usb-panel.d.ts +5 -5
  183. package/dist/components/native-capabilities/usb-panel.js +15 -15
  184. package/dist/components/native-capabilities/use-capability.d.ts +1 -1
  185. package/dist/components/native-capabilities/use-capability.js +1 -1
  186. package/dist/components/rich-media-player.js +3 -3
  187. package/dist/components/ui/accordion.js +3 -3
  188. package/dist/components/ui/alert-dialog.d.ts +2 -2
  189. package/dist/components/ui/alert-dialog.d.ts.map +1 -1
  190. package/dist/components/ui/alert-dialog.js +16 -10
  191. package/dist/components/ui/alert.d.ts +1 -1
  192. package/dist/components/ui/alert.d.ts.map +1 -1
  193. package/dist/components/ui/alert.js +11 -11
  194. package/dist/components/ui/app-frame.d.ts +7 -1
  195. package/dist/components/ui/app-frame.d.ts.map +1 -1
  196. package/dist/components/ui/app-frame.js +52 -16
  197. package/dist/components/ui/avatar.js +5 -5
  198. package/dist/components/ui/badge.d.ts +1 -1
  199. package/dist/components/ui/badge.js +4 -4
  200. package/dist/components/ui/breadcrumb.js +2 -2
  201. package/dist/components/ui/button-group.d.ts +1 -1
  202. package/dist/components/ui/button-group.js +4 -4
  203. package/dist/components/ui/button.d.ts +1 -1
  204. package/dist/components/ui/button.d.ts.map +1 -1
  205. package/dist/components/ui/button.js +16 -16
  206. package/dist/components/ui/calendar.d.ts +1 -1
  207. package/dist/components/ui/calendar.d.ts.map +1 -1
  208. package/dist/components/ui/calendar.js +15 -15
  209. package/dist/components/ui/card.js +3 -3
  210. package/dist/components/ui/carousel.d.ts +1 -1
  211. package/dist/components/ui/carousel.js +4 -4
  212. package/dist/components/ui/chart.js +5 -5
  213. package/dist/components/ui/checkbox.d.ts.map +1 -1
  214. package/dist/components/ui/checkbox.js +2 -2
  215. package/dist/components/ui/collapsible.js +3 -3
  216. package/dist/components/ui/color-well.js +2 -2
  217. package/dist/components/ui/combobox.js +9 -9
  218. package/dist/components/ui/command.d.ts +1 -1
  219. package/dist/components/ui/command.d.ts.map +1 -1
  220. package/dist/components/ui/command.js +9 -9
  221. package/dist/components/ui/confirm-dialog.d.ts +1 -1
  222. package/dist/components/ui/confirm-dialog.js +2 -2
  223. package/dist/components/ui/context-menu.d.ts +16 -5
  224. package/dist/components/ui/context-menu.d.ts.map +1 -1
  225. package/dist/components/ui/context-menu.js +92 -16
  226. package/dist/components/ui/date-field.d.ts.map +1 -1
  227. package/dist/components/ui/date-field.js +8 -8
  228. package/dist/components/ui/date-picker.d.ts +2 -2
  229. package/dist/components/ui/date-picker.js +7 -7
  230. package/dist/components/ui/dialog.d.ts +2 -2
  231. package/dist/components/ui/dialog.d.ts.map +1 -1
  232. package/dist/components/ui/dialog.js +14 -8
  233. package/dist/components/ui/drawer.js +4 -4
  234. package/dist/components/ui/dropdown-menu.d.ts +15 -5
  235. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  236. package/dist/components/ui/dropdown-menu.js +98 -16
  237. package/dist/components/ui/edge-fade.js +1 -1
  238. package/dist/components/ui/empty.d.ts +1 -1
  239. package/dist/components/ui/empty.js +5 -5
  240. package/dist/components/ui/error-boundary-view.d.ts.map +1 -1
  241. package/dist/components/ui/error-boundary-view.js +3 -3
  242. package/dist/components/ui/field.d.ts +1 -1
  243. package/dist/components/ui/field.d.ts.map +1 -1
  244. package/dist/components/ui/field.js +9 -9
  245. package/dist/components/ui/form.js +4 -4
  246. package/dist/components/ui/grid.d.ts.map +1 -1
  247. package/dist/components/ui/grid.js +5 -5
  248. package/dist/components/ui/hover-card.js +2 -2
  249. package/dist/components/ui/icon-button.d.ts +1 -1
  250. package/dist/components/ui/icon-button.js +3 -3
  251. package/dist/components/ui/index.d.ts +77 -77
  252. package/dist/components/ui/index.js +77 -77
  253. package/dist/components/ui/input-group.d.ts +2 -2
  254. package/dist/components/ui/input-group.js +14 -14
  255. package/dist/components/ui/input-otp.js +3 -3
  256. package/dist/components/ui/input.js +2 -2
  257. package/dist/components/ui/inspector.d.ts +1 -1
  258. package/dist/components/ui/inspector.js +6 -6
  259. package/dist/components/ui/item.d.ts +1 -1
  260. package/dist/components/ui/item.js +7 -7
  261. package/dist/components/ui/kbd.js +2 -2
  262. package/dist/components/ui/label.js +2 -2
  263. package/dist/components/ui/list.d.ts.map +1 -1
  264. package/dist/components/ui/list.js +5 -5
  265. package/dist/components/ui/material.js +3 -3
  266. package/dist/components/ui/menu-items.d.ts +28 -0
  267. package/dist/components/ui/menu-items.d.ts.map +1 -0
  268. package/dist/components/ui/menu-items.js +111 -0
  269. package/dist/components/ui/menubar.js +11 -11
  270. package/dist/components/ui/message-scroller-controller.d.ts +1 -1
  271. package/dist/components/ui/message-scroller-controller.js +1 -1
  272. package/dist/components/ui/message-scroller-primitive.d.ts +1 -1
  273. package/dist/components/ui/message-scroller-primitive.js +1 -1
  274. package/dist/components/ui/message-scroller.d.ts +2 -2
  275. package/dist/components/ui/message-scroller.js +3 -3
  276. package/dist/components/ui/navigation-button-group.d.ts +2 -2
  277. package/dist/components/ui/navigation-button-group.js +2 -2
  278. package/dist/components/ui/navigation-menu.js +6 -6
  279. package/dist/components/ui/notification-dot.js +2 -2
  280. package/dist/components/ui/number-input.js +8 -8
  281. package/dist/components/ui/pagination.d.ts +1 -1
  282. package/dist/components/ui/pagination.js +2 -2
  283. package/dist/components/ui/panel.d.ts +1 -1
  284. package/dist/components/ui/panel.js +3 -3
  285. package/dist/components/ui/popover.d.ts +1 -1
  286. package/dist/components/ui/popover.js +3 -3
  287. package/dist/components/ui/progress.js +2 -2
  288. package/dist/components/ui/radio-group.d.ts.map +1 -1
  289. package/dist/components/ui/radio-group.js +2 -2
  290. package/dist/components/ui/resizable.d.ts +1 -1
  291. package/dist/components/ui/resizable.d.ts.map +1 -1
  292. package/dist/components/ui/resizable.js +15 -4
  293. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  294. package/dist/components/ui/scroll-area.js +3 -3
  295. package/dist/components/ui/search-field.js +7 -7
  296. package/dist/components/ui/segmented-control.js +9 -9
  297. package/dist/components/ui/select.d.ts.map +1 -1
  298. package/dist/components/ui/select.js +6 -6
  299. package/dist/components/ui/separator.js +1 -1
  300. package/dist/components/ui/sheet.js +4 -4
  301. package/dist/components/ui/sidebar.d.ts +5 -5
  302. package/dist/components/ui/sidebar.d.ts.map +1 -1
  303. package/dist/components/ui/sidebar.js +111 -24
  304. package/dist/components/ui/skeleton.js +2 -2
  305. package/dist/components/ui/slider.d.ts +3 -1
  306. package/dist/components/ui/slider.d.ts.map +1 -1
  307. package/dist/components/ui/slider.js +3 -3
  308. package/dist/components/ui/sonner.js +1 -1
  309. package/dist/components/ui/spinner.js +1 -1
  310. package/dist/components/ui/split-view.js +1 -1
  311. package/dist/components/ui/status.d.ts +1 -1
  312. package/dist/components/ui/status.d.ts.map +1 -1
  313. package/dist/components/ui/status.js +10 -9
  314. package/dist/components/ui/switch.js +2 -2
  315. package/dist/components/ui/table.d.ts.map +1 -1
  316. package/dist/components/ui/table.js +7 -7
  317. package/dist/components/ui/tabs.js +3 -3
  318. package/dist/components/ui/text.d.ts +2 -2
  319. package/dist/components/ui/text.js +19 -19
  320. package/dist/components/ui/textarea.js +2 -2
  321. package/dist/components/ui/toggle-group.d.ts +1 -1
  322. package/dist/components/ui/toggle-group.js +4 -4
  323. package/dist/components/ui/toggle.d.ts +1 -1
  324. package/dist/components/ui/toggle.js +10 -10
  325. package/dist/components/ui/toolbar.d.ts +7 -7
  326. package/dist/components/ui/toolbar.js +7 -7
  327. package/dist/components/ui/tooltip.d.ts +2 -2
  328. package/dist/components/ui/tooltip.js +5 -5
  329. package/dist/index.d.ts +21 -20
  330. package/dist/index.d.ts.map +1 -1
  331. package/dist/index.js +21 -20
  332. package/dist/lib/frame-lifecycle.d.ts +27 -0
  333. package/dist/lib/frame-lifecycle.d.ts.map +1 -1
  334. package/dist/lib/frame-lifecycle.js +136 -0
  335. package/dist/lib/host-date-time-picker.d.ts +1 -1
  336. package/dist/lib/host-date-time-picker.js +1 -1
  337. package/dist/lib/host-file-dialog.d.ts +1 -1
  338. package/dist/lib/host-file-dialog.js +1 -1
  339. package/dist/lib/host-native-menu.d.ts +48 -7
  340. package/dist/lib/host-native-menu.d.ts.map +1 -1
  341. package/dist/lib/host-native-menu.js +56 -1
  342. package/dist/lib/host-services.js +1 -1
  343. package/dist/lib/host-share.d.ts +1 -1
  344. package/dist/lib/host-share.js +1 -1
  345. package/dist/lib/host-web-surface.d.ts +31 -0
  346. package/dist/lib/host-web-surface.d.ts.map +1 -0
  347. package/dist/lib/host-web-surface.js +116 -0
  348. package/dist/lib/native-capabilities/access.d.ts +2 -2
  349. package/dist/lib/native-capabilities/access.js +2 -2
  350. package/dist/lib/native-capabilities/bluetooth-access.d.ts +1 -1
  351. package/dist/lib/native-capabilities/bluetooth-access.js +2 -2
  352. package/dist/lib/native-capabilities/bluetooth-connection.d.ts +1 -1
  353. package/dist/lib/native-capabilities/bluetooth-connection.js +1 -1
  354. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +1 -1
  355. package/dist/lib/native-capabilities/bluetooth-gatt.js +1 -1
  356. package/dist/lib/native-capabilities/bluetooth-internal.d.ts +2 -2
  357. package/dist/lib/native-capabilities/bluetooth-internal.js +1 -1
  358. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +2 -2
  359. package/dist/lib/native-capabilities/bluetooth-native-fallback.js +2 -2
  360. package/dist/lib/native-capabilities/bluetooth.d.ts +6 -6
  361. package/dist/lib/native-capabilities/bluetooth.js +4 -4
  362. package/dist/lib/native-capabilities/bridge.d.ts +1 -1
  363. package/dist/lib/native-capabilities/bridge.js +2 -2
  364. package/dist/lib/native-capabilities/capabilities.d.ts +1 -1
  365. package/dist/lib/native-capabilities/capabilities.js +1 -1
  366. package/dist/lib/native-capabilities/clipboard.js +2 -2
  367. package/dist/lib/native-capabilities/device-io-errors.d.ts +1 -1
  368. package/dist/lib/native-capabilities/device-io-errors.js +1 -1
  369. package/dist/lib/native-capabilities/displays.d.ts +1 -1
  370. package/dist/lib/native-capabilities/displays.js +1 -1
  371. package/dist/lib/native-capabilities/global-shortcuts.d.ts +2 -2
  372. package/dist/lib/native-capabilities/global-shortcuts.js +1 -1
  373. package/dist/lib/native-capabilities/haptics.d.ts +1 -1
  374. package/dist/lib/native-capabilities/haptics.js +1 -1
  375. package/dist/lib/native-capabilities/hid-native.d.ts +2 -2
  376. package/dist/lib/native-capabilities/hid-native.js +3 -3
  377. package/dist/lib/native-capabilities/hid.js +5 -5
  378. package/dist/lib/native-capabilities/index.d.ts +39 -39
  379. package/dist/lib/native-capabilities/index.js +21 -21
  380. package/dist/lib/native-capabilities/local-authentication.d.ts +1 -1
  381. package/dist/lib/native-capabilities/local-authentication.js +1 -1
  382. package/dist/lib/native-capabilities/location.js +1 -1
  383. package/dist/lib/native-capabilities/media-permissions.d.ts +1 -1
  384. package/dist/lib/native-capabilities/media-permissions.js +1 -1
  385. package/dist/lib/native-capabilities/media.d.ts +1 -1
  386. package/dist/lib/native-capabilities/media.js +2 -2
  387. package/dist/lib/native-capabilities/midi-access.d.ts +1 -1
  388. package/dist/lib/native-capabilities/midi-access.js +3 -3
  389. package/dist/lib/native-capabilities/midi-internal.d.ts +1 -1
  390. package/dist/lib/native-capabilities/midi-internal.js +1 -1
  391. package/dist/lib/native-capabilities/midi-native-fallback.d.ts +1 -1
  392. package/dist/lib/native-capabilities/midi-native-fallback.js +2 -2
  393. package/dist/lib/native-capabilities/midi-ports.d.ts +1 -1
  394. package/dist/lib/native-capabilities/midi-ports.js +1 -1
  395. package/dist/lib/native-capabilities/midi.d.ts +5 -5
  396. package/dist/lib/native-capabilities/midi.js +3 -3
  397. package/dist/lib/native-capabilities/native-device-io.d.ts +1 -1
  398. package/dist/lib/native-capabilities/native-device-io.js +1 -1
  399. package/dist/lib/native-capabilities/native-device-lifecycle.js +1 -1
  400. package/dist/lib/native-capabilities/notifications.d.ts +2 -2
  401. package/dist/lib/native-capabilities/notifications.js +1 -1
  402. package/dist/lib/native-capabilities/power-session.d.ts +2 -2
  403. package/dist/lib/native-capabilities/power-session.js +1 -1
  404. package/dist/lib/native-capabilities/secure-storage.d.ts +1 -1
  405. package/dist/lib/native-capabilities/secure-storage.js +1 -1
  406. package/dist/lib/native-capabilities/serial-native.d.ts +2 -2
  407. package/dist/lib/native-capabilities/serial-native.js +3 -3
  408. package/dist/lib/native-capabilities/serial.js +5 -5
  409. package/dist/lib/native-capabilities/system-audio.d.ts +1 -1
  410. package/dist/lib/native-capabilities/system-audio.js +1 -1
  411. package/dist/lib/native-capabilities/usb-native.d.ts +2 -2
  412. package/dist/lib/native-capabilities/usb-native.js +3 -3
  413. package/dist/lib/native-capabilities/usb.js +5 -5
  414. package/dist/lib/native-hardware/bluetooth-access.d.ts +1 -1
  415. package/dist/lib/native-hardware/bluetooth-access.js +1 -1
  416. package/dist/lib/native-hardware/bluetooth-connection.d.ts +1 -1
  417. package/dist/lib/native-hardware/bluetooth-connection.js +1 -1
  418. package/dist/lib/native-hardware/bluetooth-gatt.d.ts +1 -1
  419. package/dist/lib/native-hardware/bluetooth-gatt.js +1 -1
  420. package/dist/lib/native-hardware/bluetooth-internal.d.ts +2 -2
  421. package/dist/lib/native-hardware/bluetooth-internal.js +1 -1
  422. package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts +2 -2
  423. package/dist/lib/native-hardware/bluetooth-native-fallback.js +2 -2
  424. package/dist/lib/native-hardware/bluetooth.d.ts +6 -6
  425. package/dist/lib/native-hardware/bluetooth.js +4 -4
  426. package/dist/lib/native-hardware/bridge.d.ts +1 -1
  427. package/dist/lib/native-hardware/bridge.js +2 -2
  428. package/dist/lib/native-hardware/capabilities.d.ts +1 -1
  429. package/dist/lib/native-hardware/capabilities.js +1 -1
  430. package/dist/lib/native-hardware/clipboard.js +1 -1
  431. package/dist/lib/native-hardware/device-io-errors.d.ts +1 -1
  432. package/dist/lib/native-hardware/device-io-errors.js +1 -1
  433. package/dist/lib/native-hardware/displays.d.ts +1 -1
  434. package/dist/lib/native-hardware/displays.js +1 -1
  435. package/dist/lib/native-hardware/global-shortcuts.d.ts +2 -2
  436. package/dist/lib/native-hardware/global-shortcuts.js +1 -1
  437. package/dist/lib/native-hardware/haptics.d.ts +1 -1
  438. package/dist/lib/native-hardware/haptics.js +1 -1
  439. package/dist/lib/native-hardware/hid-native.d.ts +2 -2
  440. package/dist/lib/native-hardware/hid-native.js +3 -3
  441. package/dist/lib/native-hardware/hid.js +4 -4
  442. package/dist/lib/native-hardware/index.d.ts +37 -37
  443. package/dist/lib/native-hardware/index.js +20 -20
  444. package/dist/lib/native-hardware/local-authentication.d.ts +1 -1
  445. package/dist/lib/native-hardware/local-authentication.js +1 -1
  446. package/dist/lib/native-hardware/location.js +1 -1
  447. package/dist/lib/native-hardware/media-permissions.d.ts +1 -1
  448. package/dist/lib/native-hardware/media-permissions.js +1 -1
  449. package/dist/lib/native-hardware/media.d.ts +1 -1
  450. package/dist/lib/native-hardware/media.js +1 -1
  451. package/dist/lib/native-hardware/midi-access.d.ts +1 -1
  452. package/dist/lib/native-hardware/midi-access.js +2 -2
  453. package/dist/lib/native-hardware/midi-internal.d.ts +1 -1
  454. package/dist/lib/native-hardware/midi-internal.js +1 -1
  455. package/dist/lib/native-hardware/midi-native-fallback.d.ts +1 -1
  456. package/dist/lib/native-hardware/midi-native-fallback.js +2 -2
  457. package/dist/lib/native-hardware/midi-ports.d.ts +1 -1
  458. package/dist/lib/native-hardware/midi-ports.js +1 -1
  459. package/dist/lib/native-hardware/midi.d.ts +5 -5
  460. package/dist/lib/native-hardware/midi.js +3 -3
  461. package/dist/lib/native-hardware/native-device-io.d.ts +1 -1
  462. package/dist/lib/native-hardware/native-device-io.js +1 -1
  463. package/dist/lib/native-hardware/native-device-lifecycle.js +1 -1
  464. package/dist/lib/native-hardware/notifications.d.ts +2 -2
  465. package/dist/lib/native-hardware/notifications.js +1 -1
  466. package/dist/lib/native-hardware/power-session.d.ts +2 -2
  467. package/dist/lib/native-hardware/power-session.js +1 -1
  468. package/dist/lib/native-hardware/secure-storage.d.ts +1 -1
  469. package/dist/lib/native-hardware/secure-storage.js +1 -1
  470. package/dist/lib/native-hardware/serial-native.d.ts +2 -2
  471. package/dist/lib/native-hardware/serial-native.js +3 -3
  472. package/dist/lib/native-hardware/serial.js +4 -4
  473. package/dist/lib/native-hardware/system-audio.d.ts +1 -1
  474. package/dist/lib/native-hardware/system-audio.js +1 -1
  475. package/dist/lib/native-hardware/usb-native.d.ts +2 -2
  476. package/dist/lib/native-hardware/usb-native.js +3 -3
  477. package/dist/lib/native-hardware/usb.js +4 -4
  478. package/dist/lib/theme.js +1 -1
  479. package/docs/design-tokens.md +28 -6
  480. package/docs/foundations.md +4 -2
  481. package/package.json +4 -2
  482. package/src/components/ui/confirm-dialog.md +97 -0
  483. package/src/components/ui/context-menu.md +158 -0
  484. package/src/components/ui/dropdown-menu.md +165 -0
  485. package/src/components/ui/hover-card.md +90 -0
  486. package/src/components/ui/select.md +111 -0
  487. package/src/lib/host-date-time-picker.md +29 -0
  488. package/src/lib/host-file-dialog.md +76 -0
  489. package/src/lib/host-native-menu.md +67 -0
  490. package/src/lib/host-share.md +36 -0
  491. package/src/lib/host-web-surface.md +66 -0
  492. package/src/styles/index.css +141 -68
@@ -2,15 +2,15 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { BatteryCharging, Plug, RefreshCw, Zap } from 'lucide-react';
4
4
  import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { getMoldableCurrentThermalState, getMoldablePowerState, getMoldableSystemIdleState, getMoldableSystemIdleTime, watchMoldablePowerSession, } from '../../lib/native-capabilities';
6
- import { cn } from '../../lib/utils';
7
- import { Button } from '../ui/button';
8
- import { Switch } from '../ui/switch';
9
- import { CapabilityBadge } from './capability-badge';
10
- import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel';
11
- import { BLOCKER_TYPES, MoldableSleepBlockerController, } from './power-blocker-controller';
12
- import { Readout, ReadoutItem } from './readout';
13
- import { StreamLog, useStreamLog } from './stream-log';
5
+ import { getMoldableCurrentThermalState, getMoldablePowerState, getMoldableSystemIdleState, getMoldableSystemIdleTime, watchMoldablePowerSession, } from '../../lib/native-capabilities/index.js';
6
+ import { cn } from '../../lib/utils.js';
7
+ import { Button } from '../ui/button.js';
8
+ import { Switch } from '../ui/switch.js';
9
+ import { CapabilityBadge } from './capability-badge.js';
10
+ import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel.js';
11
+ import { BLOCKER_TYPES, MoldableSleepBlockerController, } from './power-blocker-controller.js';
12
+ import { Readout, ReadoutItem } from './readout.js';
13
+ import { StreamLog, useStreamLog } from './stream-log.js';
14
14
  const MAX_POWER_EVENTS = 100;
15
15
  function toError(cause) {
16
16
  return cause instanceof Error ? cause : new Error(String(cause));
@@ -216,7 +216,7 @@ function BatteryGlyph({ percent, charging, className, }) {
216
216
  return (_jsxs("svg", { viewBox: "0 0 28 14", "aria-hidden": true, className: cn('h-[1em] w-[2em] shrink-0', className), children: [_jsx("rect", { x: "1", y: "1.5", width: "23", height: "11", rx: "3", fill: "none", stroke: "currentColor", strokeWidth: "1.5", className: "opacity-50" }), _jsx("rect", { x: "25.5", y: "4.75", width: "2", height: "4.5", rx: "1", fill: "currentColor", className: "opacity-50" }), _jsx("rect", { x: "3.5", y: "4", width: (clamped / 100) * 18, height: "6", rx: "1.5", className: cn('fill-current transition-all duration-500 motion-reduce:transition-none', fillClass) })] }));
217
217
  }
218
218
  function BatteryGaugeBase({ percent, charging = false, noBattery = false, className, ...props }) {
219
- return (_jsx("span", { "data-slot": "battery-gauge", "data-status": noBattery ? 'ac' : percent === undefined ? 'unknown' : 'battery', className: cn('inline-flex items-center gap-2 text-sm', className), ...props, children: noBattery ? (_jsxs(_Fragment, { children: [_jsx(Plug, { "aria-hidden": true, className: "text-muted-foreground size-[1.15em]" }), _jsx("span", { className: "font-mono tabular-nums", children: "AC power" })] })) : percent === undefined ? (_jsxs(_Fragment, { children: [_jsx(BatteryGlyph, { percent: 0, charging: false }), _jsx("span", { className: "text-muted-foreground/60 font-mono tabular-nums", children: "\u2014" })] })) : (_jsxs(_Fragment, { children: [_jsx(BatteryGlyph, { percent: percent, charging: charging }), _jsxs("span", { className: "font-mono tabular-nums", children: [Math.round(percent), "%"] }), charging ? (_jsx(Zap, { "aria-label": "Charging", className: "text-status-running size-3 fill-current" })) : null] })) }));
219
+ return (_jsx("span", { "data-slot": "battery-gauge", "data-status": noBattery ? 'ac' : percent === undefined ? 'unknown' : 'battery', className: cn('text-ui-body inline-flex items-center gap-2', className), ...props, children: noBattery ? (_jsxs(_Fragment, { children: [_jsx(Plug, { "aria-hidden": true, className: "text-muted-foreground size-[1.15em]" }), _jsx("span", { className: "font-mono tabular-nums", children: "AC power" })] })) : percent === undefined ? (_jsxs(_Fragment, { children: [_jsx(BatteryGlyph, { percent: 0, charging: false }), _jsx("span", { className: "text-muted-foreground/60 font-mono tabular-nums", children: "\u2014" })] })) : (_jsxs(_Fragment, { children: [_jsx(BatteryGlyph, { percent: percent, charging: charging }), _jsxs("span", { className: "font-mono tabular-nums", children: [Math.round(percent), "%"] }), charging ? (_jsx(Zap, { "aria-label": "Charging", className: "text-status-running size-3 fill-current" })) : null] })) }));
220
220
  }
221
221
  function ManagedBatteryGauge(props) {
222
222
  const { power } = useMoldablePower();
@@ -300,9 +300,9 @@ function PowerPanel({ className, pollIntervalMs, ...props }) {
300
300
  : power.error
301
301
  ? 'unavailable'
302
302
  : 'loading';
303
- return (_jsxs(NativeCapabilityPanel, { "data-slot": "power-panel", "data-status": status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(BatteryCharging, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Power" }), _jsx(CapabilityBadge, { capability: "power-monitor" }), _jsx(NativeCapabilityPanelAction, { children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("label", { className: "text-muted-foreground flex items-center gap-2 text-xs font-medium", children: ["Display", _jsx(Switch, { size: "sm", checked: power.sleepBlockers['prevent-display-sleep'].active, disabled: power.sleepBlockers['prevent-display-sleep'].busy, onCheckedChange: () => void power.sleepBlockers['prevent-display-sleep'].toggle(), "aria-label": "Keep the display awake" })] }), _jsxs("label", { className: "text-muted-foreground flex items-center gap-2 text-xs font-medium", children: ["App", _jsx(Switch, { size: "sm", checked: power.sleepBlockers['prevent-app-suspension'].active, disabled: power.sleepBlockers['prevent-app-suspension'].busy, onCheckedChange: () => void power.sleepBlockers['prevent-app-suspension'].toggle(), "aria-label": "Keep the app active" })] })] }) })] }), _jsx(NativeCapabilityPanelContent, { children: _jsxs("div", { className: "animate-in fade-in space-y-4 duration-300 motion-reduce:animate-none", children: [_jsx(BatteryGauge, { className: "text-xl font-medium tracking-tight sm:text-2xl", percent: battery?.chargePercent, charging: battery?.state === 'charging', noBattery: noBattery }), _jsxs(Readout, { className: "grid-cols-2 sm:grid-cols-4", children: [_jsx(ReadoutItem, { label: "Source", value: power.power ? POWER_SOURCE_LABEL[power.power.source] : null }), _jsx(ReadoutItem, { label: "State", value: battery ? capitalize(battery.state) : null }), _jsx(ReadoutItem, { label: "Thermal", value: power.thermal ? capitalize(power.thermal) : null }), _jsx(ReadoutItem, { label: "Idle", value: power.idle
303
+ return (_jsxs(NativeCapabilityPanel, { "data-slot": "power-panel", "data-status": status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(BatteryCharging, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Power" }), _jsx(CapabilityBadge, { capability: "power-monitor" }), _jsx(NativeCapabilityPanelAction, { children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("label", { className: "text-muted-foreground text-ui-caption flex items-center gap-2 font-medium", children: ["Display", _jsx(Switch, { size: "sm", checked: power.sleepBlockers['prevent-display-sleep'].active, disabled: power.sleepBlockers['prevent-display-sleep'].busy, onCheckedChange: () => void power.sleepBlockers['prevent-display-sleep'].toggle(), "aria-label": "Keep the display awake" })] }), _jsxs("label", { className: "text-muted-foreground text-ui-caption flex items-center gap-2 font-medium", children: ["App", _jsx(Switch, { size: "sm", checked: power.sleepBlockers['prevent-app-suspension'].active, disabled: power.sleepBlockers['prevent-app-suspension'].busy, onCheckedChange: () => void power.sleepBlockers['prevent-app-suspension'].toggle(), "aria-label": "Keep the app active" })] })] }) })] }), _jsx(NativeCapabilityPanelContent, { children: _jsxs("div", { className: "animate-in fade-in space-y-4 duration-300 motion-reduce:animate-none", children: [_jsx(BatteryGauge, { className: "text-ui-heading sm:text-ui-display font-medium tracking-tight", percent: battery?.chargePercent, charging: battery?.state === 'charging', noBattery: noBattery }), _jsxs(Readout, { className: "grid-cols-2 sm:grid-cols-4", children: [_jsx(ReadoutItem, { label: "Source", value: power.power ? POWER_SOURCE_LABEL[power.power.source] : null }), _jsx(ReadoutItem, { label: "State", value: battery ? capitalize(battery.state) : null }), _jsx(ReadoutItem, { label: "Thermal", value: power.thermal ? capitalize(power.thermal) : null }), _jsx(ReadoutItem, { label: "Idle", value: power.idle
304
304
  ? `${formatIdleSeconds(power.idle.seconds)} · ${power.idle.state}`
305
- : null })] }), power.error ? (_jsx("p", { className: "text-status-error text-xs", children: power.error.message })) : null, _jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "text-muted-foreground text-[10px] font-medium uppercase tracking-wider", children: "Session events" }), _jsx(StreamLog, { entries: log.entries, maxHeight: 160, emptyLabel: "No session events yet" })] })] }) }), _jsxs(NativeCapabilityPanelFooter, { children: [_jsx("span", { className: "truncate font-mono tabular-nums", children: power.updatedAt
305
+ : null })] }), power.error ? (_jsx("p", { className: "text-status-error text-ui-caption", children: power.error.message })) : null, _jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "text-muted-foreground text-11 font-medium uppercase tracking-wider", children: "Session events" }), _jsx(StreamLog, { entries: log.entries, maxHeight: 160, emptyLabel: "No session events yet" })] })] }) }), _jsxs(NativeCapabilityPanelFooter, { children: [_jsx("span", { className: "truncate font-mono tabular-nums", children: power.updatedAt
306
306
  ? `Updated ${formatClock(power.updatedAt)}`
307
307
  : 'Waiting for first reading' }), _jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": "Refresh power state", className: "ml-auto", onClick: power.refresh, children: _jsx(RefreshCw, {}) }), _jsx(Button, { variant: "ghost", size: "xs", className: "gap-1", disabled: BLOCKER_TYPES.some((type) => power.sleepBlockers[type].busy), onClick: () => void Promise.all(BLOCKER_TYPES.map((type) => power.sleepBlockers[type].check())), children: "Check blockers" })] })] }));
308
308
  }
@@ -1 +1 @@
1
- {"version":3,"file":"readout.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/readout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,iBAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAWpE;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACnE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,iBAAS,WAAW,CAAC,EACnB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,gBAAgB,2CA6BlB;AAED,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"readout.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/readout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,iBAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAWpE;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACnE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,iBAAS,WAAW,CAAC,EACnB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,gBAAgB,2CA+BlB;AAED,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { cn } from '../../lib/utils';
3
+ import { cn } from '../../lib/utils.js';
4
4
  function Readout({ className, ...props }) {
5
5
  return (_jsx("div", { "data-slot": "readout", className: cn('grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-3', className), ...props }));
6
6
  }
7
7
  function ReadoutItem({ label, value, unit, className, children, ...props }) {
8
8
  const content = children ?? value;
9
- return (_jsxs("div", { "data-slot": "readout-item", className: cn('min-w-0', className), ...props, children: [_jsx("div", { "data-slot": "readout-label", className: "text-muted-foreground text-[10px] font-medium uppercase tracking-wider", children: label }), _jsxs("div", { "data-slot": "readout-value", className: "mt-1 truncate font-mono text-sm tabular-nums", children: [content === null || content === undefined ? (_jsx("span", { className: "text-muted-foreground/60", children: "\u2014" })) : (content), unit !== undefined && content !== null && content !== undefined ? (_jsx("span", { className: "text-muted-foreground ml-1 text-xs", children: unit })) : null] })] }));
9
+ return (_jsxs("div", { "data-slot": "readout-item", className: cn('min-w-0', className), ...props, children: [_jsx("div", { "data-slot": "readout-label", className: "text-muted-foreground text-11 font-medium uppercase tracking-wider", children: label }), _jsxs("div", { "data-slot": "readout-value", className: "text-ui-body mt-1 truncate font-mono tabular-nums", children: [content === null || content === undefined ? (_jsx("span", { className: "text-muted-foreground/60", children: "\u2014" })) : (content), unit !== undefined && content !== null && content !== undefined ? (_jsx("span", { className: "text-muted-foreground text-ui-caption ml-1", children: unit })) : null] })] }));
10
10
  }
11
11
  export { Readout, ReadoutItem };
@@ -2,11 +2,11 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { MonitorOff, MonitorUp, RefreshCw, Square } from 'lucide-react';
4
4
  import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { NativeCapabilityBridgeError, getMoldableDisplayStream, getMoldableMediaPermissionStatus, requestMoldableMediaPermission, stopMoldableMediaStream, } from '../../lib/native-capabilities';
6
- import { cn } from '../../lib/utils';
7
- import { Button } from '../ui/button';
8
- import { Spinner } from '../ui/spinner';
9
- import { LiveIndicator } from './live-indicator';
5
+ import { NativeCapabilityBridgeError, getMoldableDisplayStream, getMoldableMediaPermissionStatus, requestMoldableMediaPermission, stopMoldableMediaStream, } from '../../lib/native-capabilities/index.js';
6
+ import { cn } from '../../lib/utils.js';
7
+ import { Button } from '../ui/button.js';
8
+ import { Spinner } from '../ui/spinner.js';
9
+ import { LiveIndicator } from './live-indicator.js';
10
10
  function isPermissionDenied(error) {
11
11
  if (error instanceof NativeCapabilityBridgeError) {
12
12
  return error.code === 'permission_denied';
@@ -185,7 +185,7 @@ function ScreenSharePreview({ className, withAudio = false, autoStart = false, o
185
185
  const videoTrack = active ? share.stream?.getVideoTracks()[0] : undefined;
186
186
  const settings = videoTrack?.getSettings();
187
187
  const sourceLabel = videoTrack?.label;
188
- return (_jsxs("div", { "data-slot": "screen-share-preview", "data-status": share.status, className: cn('group relative isolate aspect-video w-full overflow-hidden rounded-xl border', active ? 'bg-black' : 'bg-muted/30', className), ...props, children: [_jsx("video", { ref: videoRef, muted: true, playsInline: true, className: cn('absolute inset-0 size-full object-contain', !active && 'invisible') }), _jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0 z-30 bg-white transition-opacity duration-150", style: { opacity: flash ? 0.9 : 0 } }), active ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute left-3 top-3 z-20", children: _jsx(LiveIndicator, { variant: "rec", label: share.status === 'muted' ? 'Paused' : 'Sharing' }) }), _jsxs("div", { className: "absolute right-3 top-3 z-20 flex max-w-[70%] items-center gap-1.5", children: [sourceLabel ? (_jsx("div", { className: "truncate rounded-full border border-white/15 bg-black/60 px-2 py-0.5 font-mono text-[10px] text-white/90 backdrop-blur-sm", children: sourceLabel })) : null, settings?.width && settings.height ? (_jsxs("div", { className: "shrink-0 rounded-full border border-white/15 bg-black/60 px-2 py-0.5 font-mono text-[10px] tabular-nums text-white/90 backdrop-blur-sm", children: [settings.width, "\u00D7", settings.height] })) : null] }), _jsxs("div", { className: "absolute inset-x-0 bottom-0 z-20 flex items-end justify-end gap-2 bg-gradient-to-t from-black/70 via-black/25 to-transparent p-3 pt-10 opacity-0 transition-opacity duration-200 focus-within:opacity-100 group-hover:opacity-100", children: [onSnapshot ? (_jsx("button", { type: "button", onClick: capture, "aria-label": "Take snapshot", className: "size-9 rounded-full border-2 border-white/40 bg-white shadow-md transition-transform duration-150 hover:scale-105 active:scale-95 motion-reduce:transition-none" })) : null, _jsx(Button, { variant: "secondary", size: "icon-sm", "aria-label": "Stop sharing", onClick: share.stop, className: "border border-white/15 bg-white/10 text-white backdrop-blur-md hover:bg-white/20", children: _jsx(Square, { className: "fill-current" }) })] })] })) : (_jsx("div", { className: "animate-in fade-in absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 p-6 text-center duration-300 motion-reduce:animate-none", children: share.status === 'starting' ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { className: "text-muted-foreground" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Waiting for the source picker\u2026" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground bg-background shadow-xs flex size-10 items-center justify-center rounded-lg border [&_svg]:size-5", children: share.status === 'idle' ? _jsx(MonitorUp, {}) : _jsx(MonitorOff, {}) }), share.status === 'idle' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: "Nothing is being shared" }), _jsxs(Button, { size: "sm", onClick: () => void share.start(), children: [_jsx(MonitorUp, {}), " Share screen"] })] })) : share.status === 'denied' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm font-medium", children: "Screen recording access denied" }), _jsx("p", { className: "text-muted-foreground max-w-64 text-xs", children: "Enable screen recording for Moldable in System Settings, then try again." }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void share.start(), children: [_jsx(RefreshCw, {}), " Try again"] })] })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm font-medium", children: "Screen share unavailable" }), _jsx("p", { className: "text-muted-foreground max-w-64 text-xs", children: share.error?.message ??
188
+ return (_jsxs("div", { "data-slot": "screen-share-preview", "data-status": share.status, className: cn('rounded-container group relative isolate aspect-video w-full overflow-hidden border', active ? 'bg-black' : 'bg-muted/30', className), ...props, children: [_jsx("video", { ref: videoRef, muted: true, playsInline: true, className: cn('absolute inset-0 size-full object-contain', !active && 'invisible') }), _jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0 z-30 bg-white transition-opacity duration-150", style: { opacity: flash ? 0.9 : 0 } }), active ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute left-3 top-3 z-20", children: _jsx(LiveIndicator, { variant: "rec", label: share.status === 'muted' ? 'Paused' : 'Sharing' }) }), _jsxs("div", { className: "absolute right-3 top-3 z-20 flex max-w-[70%] items-center gap-1.5", children: [sourceLabel ? (_jsx("div", { className: "rounded-pill text-11 truncate border border-white/15 bg-black/60 px-2 py-0.5 font-mono text-white/90 backdrop-blur-sm", children: sourceLabel })) : null, settings?.width && settings.height ? (_jsxs("div", { className: "rounded-pill text-11 shrink-0 border border-white/15 bg-black/60 px-2 py-0.5 font-mono tabular-nums text-white/90 backdrop-blur-sm", children: [settings.width, "\u00D7", settings.height] })) : null] }), _jsxs("div", { className: "absolute inset-x-0 bottom-0 z-20 flex items-end justify-end gap-2 bg-gradient-to-t from-black/70 via-black/25 to-transparent p-3 pt-10 opacity-0 transition-opacity duration-200 focus-within:opacity-100 group-hover:opacity-100", children: [onSnapshot ? (_jsx("button", { type: "button", onClick: capture, "aria-label": "Take snapshot", className: "rounded-pill size-9 border-2 border-white/40 bg-white shadow-md transition-transform duration-150 hover:scale-105 active:scale-95 motion-reduce:transition-none" })) : null, _jsx(Button, { variant: "secondary", size: "icon-sm", "aria-label": "Stop sharing", onClick: share.stop, className: "border border-white/15 bg-white/10 text-white backdrop-blur-md hover:bg-white/20", children: _jsx(Square, { className: "fill-current" }) })] })] })) : (_jsx("div", { className: "animate-in fade-in absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 p-6 text-center duration-300 motion-reduce:animate-none", children: share.status === 'starting' ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { className: "text-muted-foreground" }), _jsx("p", { className: "text-muted-foreground text-ui-caption", children: "Waiting for the source picker\u2026" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground bg-background shadow-xs rounded-container flex size-10 items-center justify-center border [&_svg]:size-5", children: share.status === 'idle' ? _jsx(MonitorUp, {}) : _jsx(MonitorOff, {}) }), share.status === 'idle' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-muted-foreground text-ui-body", children: "Nothing is being shared" }), _jsxs(Button, { size: "sm", onClick: () => void share.start(), children: [_jsx(MonitorUp, {}), " Share screen"] })] })) : share.status === 'denied' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-ui-body font-medium", children: "Screen recording access denied" }), _jsx("p", { className: "text-muted-foreground text-ui-caption max-w-64", children: "Enable screen recording for Moldable in System Settings, then try again." }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void share.start(), children: [_jsx(RefreshCw, {}), " Try again"] })] })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-ui-body font-medium", children: "Screen share unavailable" }), _jsx("p", { className: "text-muted-foreground text-ui-caption max-w-64", children: share.error?.message ??
189
189
  'The screen share could not be started.' }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void share.start(), children: [_jsx(RefreshCw, {}), " Try again"] })] }))] })) }))] }));
190
190
  }
191
191
  export { ScreenSharePreview };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { type MoldableSecureStorageDiagnostics, type MoldableSecureStorageEntryMetadata } from '../../lib/native-capabilities';
2
+ import { type MoldableSecureStorageDiagnostics, type MoldableSecureStorageEntryMetadata } from '../../lib/native-capabilities/index.js';
3
3
  export type MoldableSecureStorageStatus = 'loading' | 'ready' | 'error';
4
4
  export interface MoldableSecureEntryValidation {
5
5
  valid: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"secure-storage-panel.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/secure-storage-panel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,gCAAgC,EACrC,KAAK,kCAAkC,EAQxC,MAAM,+BAA+B,CAAA;AAiBtC,MAAM,MAAM,2BAA2B,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAIvE,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,OAAO,CAAA;IACd,mFAAmF;IACnF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,KAAK,SAAK,GACT,6BAA6B,CAwB/B;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB;;;;;;eAqCxB,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;eAgBlB,MAAM,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;kBAcrD,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;;EA2BxC;AAWD;;;GAGG;AACH,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CA0K7B;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"secure-storage-panel.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/secure-storage-panel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,gCAAgC,EACrC,KAAK,kCAAkC,EAQxC,MAAM,+BAA+B,CAAA;AAiBtC,MAAM,MAAM,2BAA2B,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAIvE,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,OAAO,CAAA;IACd,mFAAmF;IACnF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,KAAK,SAAK,GACT,6BAA6B,CAwB/B;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB;;;;;;eAqCxB,MAAM,SAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;eAgBlB,MAAM,KAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;kBAcrD,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;;EA2BxC;AAWD;;;GAGG;AACH,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAkL7B;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -2,15 +2,15 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { Eye, EyeOff, KeyRound, Trash2 } from 'lucide-react';
4
4
  import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { SECURE_STORAGE_MAX_KEY_LENGTH, SECURE_STORAGE_MAX_VALUE_BYTES, deleteMoldableSecureValue, getMoldableSecureStorageDiagnostics, getMoldableSecureValue, listMoldableSecureValues, setMoldableSecureValue, } from '../../lib/native-capabilities';
6
- import { Badge } from '../ui/badge';
7
- import { Button } from '../ui/button';
8
- import { Input } from '../ui/input';
9
- import { Skeleton } from '../ui/skeleton';
10
- import { Spinner } from '../ui/spinner';
11
- import { CapabilityBadge } from './capability-badge';
12
- import { DeviceList, DeviceListEmpty, DeviceListItem } from './device-list';
13
- import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel';
5
+ import { SECURE_STORAGE_MAX_KEY_LENGTH, SECURE_STORAGE_MAX_VALUE_BYTES, deleteMoldableSecureValue, getMoldableSecureStorageDiagnostics, getMoldableSecureValue, listMoldableSecureValues, setMoldableSecureValue, } from '../../lib/native-capabilities/index.js';
6
+ import { Badge } from '../ui/badge.js';
7
+ import { Button } from '../ui/button.js';
8
+ import { Input } from '../ui/input.js';
9
+ import { Skeleton } from '../ui/skeleton.js';
10
+ import { Spinner } from '../ui/spinner.js';
11
+ import { CapabilityBadge } from './capability-badge.js';
12
+ import { DeviceList, DeviceListEmpty, DeviceListItem } from './device-list.js';
13
+ import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel.js';
14
14
  const SECURE_STORAGE_KEY_PATTERN = /^[A-Za-z0-9._-]+$/;
15
15
  /**
16
16
  * Client-side mirror of the library's secure-storage constraints. Returns a
@@ -181,9 +181,9 @@ function SecureStoragePanel({ className, ...props }) {
181
181
  hide(key);
182
182
  await storage.remove(key);
183
183
  };
184
- return (_jsxs(NativeCapabilityPanel, { "data-slot": "secure-storage-panel", "data-status": storage.status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(KeyRound, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Secure Storage" }), _jsx(CapabilityBadge, { capability: "secure-storage" }), _jsx(NativeCapabilityPanelAction, { children: storage.diagnostics ? (_jsx(Badge, { variant: "outline", className: "font-mono text-[10px]", children: storage.diagnostics.backend })) : null })] }), _jsxs(NativeCapabilityPanelContent, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: draftKey, placeholder: "key", maxLength: SECURE_STORAGE_MAX_KEY_LENGTH, "aria-label": "Secret key", autoCapitalize: "off", autoComplete: "off", autoCorrect: "off", spellCheck: false, className: "font-mono", onChange: (event) => setDraftKey(event.target.value) }), _jsx(Input, { value: draftValue, type: "password", placeholder: "value", "aria-label": "Secret value", autoComplete: "new-password", onChange: (event) => setDraftValue(event.target.value) }), _jsxs(Button, { disabled: !canStore, onClick: () => void store(), children: [storing ? _jsx(Spinner, {}) : null, "Store"] })] }), validation.message ? (_jsx("p", { className: "text-status-error text-xs", children: validation.message })) : null, storage.error ? (_jsx("p", { className: "text-status-error text-xs", children: storage.error.message })) : null, storage.status === 'loading' && storage.keys.length === 0 ? (_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-12 w-full rounded-lg" }), _jsx(Skeleton, { className: "h-12 w-full rounded-lg" })] })) : storage.keys.length === 0 ? (_jsx(DeviceList, { children: _jsxs(DeviceListEmpty, { icon: _jsx(KeyRound, {}), children: [_jsx("span", { className: "text-sm font-medium", children: "Nothing stored" }), _jsx("span", { className: "text-xs", children: "Values are encrypted by the OS keychain." })] }) })) : (_jsx(DeviceList, { children: storage.keys.map((entry) => {
184
+ return (_jsxs(NativeCapabilityPanel, { "data-slot": "secure-storage-panel", "data-status": storage.status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(KeyRound, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Secure Storage" }), _jsx(CapabilityBadge, { capability: "secure-storage" }), _jsx(NativeCapabilityPanelAction, { children: storage.diagnostics ? (_jsx(Badge, { variant: "outline", className: "text-11 font-mono", children: storage.diagnostics.backend })) : null })] }), _jsxs(NativeCapabilityPanelContent, { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: draftKey, placeholder: "key", maxLength: SECURE_STORAGE_MAX_KEY_LENGTH, "aria-label": "Secret key", autoCapitalize: "off", autoComplete: "off", autoCorrect: "off", spellCheck: false, className: "font-mono", onChange: (event) => setDraftKey(event.target.value) }), _jsx(Input, { value: draftValue, type: "password", placeholder: "value", "aria-label": "Secret value", autoComplete: "new-password", onChange: (event) => setDraftValue(event.target.value) }), _jsxs(Button, { disabled: !canStore, onClick: () => void store(), children: [storing ? _jsx(Spinner, {}) : null, "Store"] })] }), validation.message ? (_jsx("p", { className: "text-status-error text-ui-caption", children: validation.message })) : null, storage.error ? (_jsx("p", { className: "text-status-error text-ui-caption", children: storage.error.message })) : null, storage.status === 'loading' && storage.keys.length === 0 ? (_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "rounded-container h-12 w-full" }), _jsx(Skeleton, { className: "rounded-container h-12 w-full" })] })) : storage.keys.length === 0 ? (_jsx(DeviceList, { children: _jsxs(DeviceListEmpty, { icon: _jsx(KeyRound, {}), children: [_jsx("span", { className: "text-ui-body font-medium", children: "Nothing stored" }), _jsx("span", { className: "text-ui-caption", children: "Values are encrypted by the OS keychain." })] }) })) : (_jsx(DeviceList, { children: storage.keys.map((entry) => {
185
185
  const revealedValue = revealed[entry.key];
186
- return (_jsx(DeviceListItem, { icon: _jsx(KeyRound, {}), name: _jsx("span", { className: "font-mono text-xs", children: entry.key }), description: revealedValue !== undefined
186
+ return (_jsx(DeviceListItem, { icon: _jsx(KeyRound, {}), name: _jsx("span", { className: "text-ui-caption font-mono", children: entry.key }), description: revealedValue !== undefined
187
187
  ? revealedValue
188
188
  : entry.updatedAtMs > entry.createdAtMs
189
189
  ? `Updated ${formatEntryTimestamp(entry.updatedAtMs)}`
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { type MoldableSerialInputSignals, type MoldableSerialOutputSignals, type MoldableSerialPort, type MoldableSerialPortFilter, type MoldableSerialPortInfo, type MoldableSerialRequestOptions } from '../../lib/native-capabilities';
2
+ import { type MoldableSerialInputSignals, type MoldableSerialOutputSignals, type MoldableSerialPort, type MoldableSerialPortFilter, type MoldableSerialPortInfo, type MoldableSerialRequestOptions } from '../../lib/native-capabilities/index.js';
3
3
  export type MoldableSerialStatus = 'idle' | 'connecting' | 'connected' | 'error';
4
4
  export interface UseMoldableSerialOptions {
5
5
  /** Baud rate used when `connect` does not override it. Defaults to 115200. */
@@ -34,7 +34,7 @@ export declare function useMoldableSerial(options?: UseMoldableSerialOptions): {
34
34
  error: Error | null;
35
35
  signals: MoldableSerialSignalsState;
36
36
  inputSignals: MoldableSerialInputSignals | null;
37
- entries: import("./stream-log").StreamLogEntry[];
37
+ entries: import("./stream-log.js").StreamLogEntry[];
38
38
  rxBytes: number;
39
39
  txBytes: number;
40
40
  connect: (overrides?: MoldableSerialConnectOptions) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"serial-console.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/serial-console.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EASlC,MAAM,+BAA+B,CAAA;AAyBtC,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAA;AA2BhF,MAAM,WAAW,wBAAwB;IACvC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;IAC7C,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,4BAA4B,CAAC,kBAAkB,CAAC,CAAA;IACnE,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;IACpC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;CAC9C;AAED,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,EAAE,OAAO,CAAA;IAC1B,aAAa,EAAE,OAAO,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAQD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B;;;;;;;;;;0BAkHlD,4BAA4B;;;iBA0HjC,MAAM,GAAG,UAAU;uBAsBnB,2BAA2B;;;EAiE3C;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACrE,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;IAC7C,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,4BAA4B,CAAC,kBAAkB,CAAC,CAAA;IACnE,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CACrC;AAED;;;GAGG;AACH,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAA4B,EAC5B,OAAO,EACP,gBAAgB,EAChB,MAAM,EACN,GAAG,KAAK,EACT,EAAE,kBAAkB,2CAsSpB;AAED,OAAO,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"serial-console.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/serial-console.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EASlC,MAAM,+BAA+B,CAAA;AAyBtC,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,OAAO,CAAA;AA2BhF,MAAM,WAAW,wBAAwB;IACvC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;IAC7C,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,4BAA4B,CAAC,kBAAkB,CAAC,CAAA;IACnE,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;IACpC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;CAC9C;AAED,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,EAAE,OAAO,CAAA;IAC1B,aAAa,EAAE,OAAO,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAQD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B;;;;;;;;;;0BAkHlD,4BAA4B;;;iBA0HjC,MAAM,GAAG,UAAU;uBAsBnB,2BAA2B;;;EAiE3C;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACrE,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;IAC7C,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,4BAA4B,CAAC,kBAAkB,CAAC,CAAA;IACnE,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAA;CACrC;AAED;;;GAGG;AACH,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAA4B,EAC5B,OAAO,EACP,gBAAgB,EAChB,MAAM,EACN,GAAG,KAAK,EACT,EAAE,kBAAkB,2CA0SpB;AAED,OAAO,EAAE,aAAa,EAAE,CAAA"}
@@ -2,16 +2,16 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { Cable, CornerDownLeft, Plug, RefreshCw, ShieldX, Unplug, } from 'lucide-react';
4
4
  import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { closeMoldableSerialPort, forgetMoldableSerialPort, getMoldableSerialSignals, openMoldableSerialPort, readMoldableSerialPort, requestMoldableSerialPort, setMoldableSerialSignals, writeMoldableSerialPort, } from '../../lib/native-capabilities';
6
- import { Button } from '../ui/button';
7
- import { Input } from '../ui/input';
8
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select';
9
- import { Spinner } from '../ui/spinner';
10
- import { Switch } from '../ui/switch';
11
- import { CapabilityBadge } from './capability-badge';
12
- import { LiveIndicator } from './live-indicator';
13
- import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel';
14
- import { StreamLog, useStreamLog } from './stream-log';
5
+ import { closeMoldableSerialPort, forgetMoldableSerialPort, getMoldableSerialSignals, openMoldableSerialPort, readMoldableSerialPort, requestMoldableSerialPort, setMoldableSerialSignals, writeMoldableSerialPort, } from '../../lib/native-capabilities/index.js';
6
+ import { Button } from '../ui/button.js';
7
+ import { Input } from '../ui/input.js';
8
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select.js';
9
+ import { Spinner } from '../ui/spinner.js';
10
+ import { Switch } from '../ui/switch.js';
11
+ import { CapabilityBadge } from './capability-badge.js';
12
+ import { LiveIndicator } from './live-indicator.js';
13
+ import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel.js';
14
+ import { StreamLog, useStreamLog } from './stream-log.js';
15
15
  const BAUD_RATES = [9600, 19200, 38400, 57600, 115200, 230400];
16
16
  const DEFAULT_BAUD_RATE = 115200;
17
17
  function toError(cause) {
@@ -394,6 +394,6 @@ function SerialConsole({ className, baudRate = DEFAULT_BAUD_RATE, filters, selec
394
394
  void serial.send(draft);
395
395
  setDraft('');
396
396
  };
397
- return (_jsxs(NativeCapabilityPanel, { "data-slot": "serial-console", "data-status": serial.status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(Cable, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Serial" }), _jsx(CapabilityBadge, { capability: "serial" }), _jsx(NativeCapabilityPanelAction, { children: retainedPort ? (_jsxs(_Fragment, { children: [_jsx("span", { "data-slot": "serial-console-port", className: "animate-in fade-in text-muted-foreground bg-muted/50 rounded-md border px-2 py-0.5 font-mono text-xs tabular-nums duration-200 motion-reduce:animate-none", children: formatSerialPortLabel(serial.portInfo) }), connected ? _jsx(LiveIndicator, {}) : null, _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void serial.disconnect(), children: [_jsx(Unplug, {}), " ", connected ? 'Disconnect' : 'Retry disconnect'] })] })) : (_jsxs(_Fragment, { children: [_jsxs(Select, { value: baud, onValueChange: setBaud, disabled: connecting, children: [_jsx(SelectTrigger, { size: "sm", "aria-label": "Baud rate", className: "w-28 font-mono text-xs tabular-nums", children: _jsx(SelectValue, { placeholder: "Baud" }) }), _jsx(SelectContent, { children: rates.map((rate) => (_jsx(SelectItem, { value: String(rate), children: rate }, rate))) })] }), _jsxs(Button, { size: "sm", disabled: connecting, onClick: () => void serial.connect({ baudRate: Number(baud) }), children: [connecting ? _jsx(Spinner, {}) : _jsx(Plug, {}), connecting ? 'Connecting…' : 'Connect'] })] })) })] }), _jsxs(NativeCapabilityPanelContent, { className: "space-y-3", children: [nativePortChoices.length > 0 ? (_jsxs("div", { "data-slot": "serial-console-port-chooser", className: "bg-muted/30 space-y-2 rounded-lg border p-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-xs font-medium", children: "Choose a serial port" }), _jsx(Button, { size: "xs", variant: "ghost", onClick: cancelNativePortSelection, children: "Cancel" })] }), _jsx("div", { className: "grid gap-1.5", children: nativePortChoices.map((choice, index) => (_jsxs(Button, { size: "sm", variant: "outline", className: "justify-start font-mono", onClick: () => chooseNativePort(choice), children: [_jsx(Cable, {}), " ", formatSerialPortLabel(choice.getInfo())] }, `${formatSerialPortLabel(choice.getInfo())}-${index}`))) })] })) : null, serial.error ? (_jsx("p", { className: "text-status-error text-xs", children: serial.error.message })) : null, _jsx(StreamLog, { entries: serial.entries, maxHeight: 260, emptyLabel: connected ? 'Waiting for data' : 'Connect a port to start streaming' }), _jsxs("form", { "data-slot": "serial-console-composer", className: "flex items-center gap-2", onSubmit: submitLine, children: [_jsx(Input, { value: draft, onChange: (event) => setDraft(event.target.value), placeholder: "Send a line\u2026", disabled: !connected, spellCheck: false, autoComplete: "off", className: "h-8 flex-1 font-mono text-xs" }), _jsx(Button, { type: "submit", size: "icon-sm", variant: "outline", disabled: !connected, "aria-label": "Send line", children: _jsx(CornerDownLeft, {}) })] })] }), _jsxs(NativeCapabilityPanelFooter, { className: "flex-wrap", children: [_jsxs("label", { "data-slot": "serial-console-signal", className: "flex items-center gap-1.5", children: [_jsx(Switch, { size: "sm", checked: serial.signals.dataTerminalReady, disabled: !connected, onCheckedChange: (checked) => void serial.setSignals({ dataTerminalReady: checked }), "aria-label": "Data terminal ready" }), _jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider", children: "DTR" })] }), _jsxs("label", { "data-slot": "serial-console-signal", className: "flex items-center gap-1.5", children: [_jsx(Switch, { size: "sm", checked: serial.signals.requestToSend, disabled: !connected, onCheckedChange: (checked) => void serial.setSignals({ requestToSend: checked }), "aria-label": "Request to send" }), _jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider", children: "RTS" })] }), _jsxs("label", { "data-slot": "serial-console-signal", className: "flex items-center gap-1.5", children: [_jsx(Switch, { size: "sm", checked: serial.signals.break, disabled: !connected, onCheckedChange: (checked) => void serial.setSignals({ break: checked }), "aria-label": "Break signal" }), _jsx("span", { className: "text-[10px] font-medium uppercase tracking-wider", children: "BRK" })] }), _jsx(Button, { size: "icon-xs", variant: "ghost", disabled: !connected, onClick: () => void serial.refreshSignals(), "aria-label": "Refresh input signals", title: "Refresh input signals", children: _jsx(RefreshCw, {}) }), serial.inputSignals ? (_jsxs("span", { "data-slot": "serial-console-input-signals", className: "font-mono text-[10px] tabular-nums", children: ["CTS ", serial.inputSignals.clearToSend ? '1' : '0', " \u00B7 DCD", ' ', serial.inputSignals.dataCarrierDetect ? '1' : '0', " \u00B7 DSR", ' ', serial.inputSignals.dataSetReady ? '1' : '0', " \u00B7 RI", ' ', serial.inputSignals.ringIndicator ? '1' : '0'] })) : null, retainedPort ? (_jsxs(Button, { size: "xs", variant: "ghost", onClick: () => void serial.forget(), children: [_jsx(ShieldX, {}), " Forget"] })) : null, _jsxs("span", { "data-slot": "serial-console-counters", className: "ml-auto shrink-0 font-mono tabular-nums", children: ["RX ", serial.rxBytes, " \u00B7 TX ", serial.txBytes] })] })] }));
397
+ return (_jsxs(NativeCapabilityPanel, { "data-slot": "serial-console", "data-status": serial.status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(Cable, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Serial" }), _jsx(CapabilityBadge, { capability: "serial" }), _jsx(NativeCapabilityPanelAction, { children: retainedPort ? (_jsxs(_Fragment, { children: [_jsx("span", { "data-slot": "serial-console-port", className: "animate-in fade-in text-muted-foreground bg-muted/50 rounded-control text-ui-caption border px-2 py-0.5 font-mono tabular-nums duration-200 motion-reduce:animate-none", children: formatSerialPortLabel(serial.portInfo) }), connected ? _jsx(LiveIndicator, {}) : null, _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void serial.disconnect(), children: [_jsx(Unplug, {}), " ", connected ? 'Disconnect' : 'Retry disconnect'] })] })) : (_jsxs(_Fragment, { children: [_jsxs(Select, { value: baud, onValueChange: setBaud, disabled: connecting, children: [_jsx(SelectTrigger, { size: "sm", "aria-label": "Baud rate", className: "text-ui-caption w-28 font-mono tabular-nums", children: _jsx(SelectValue, { placeholder: "Baud" }) }), _jsx(SelectContent, { children: rates.map((rate) => (_jsx(SelectItem, { value: String(rate), children: rate }, rate))) })] }), _jsxs(Button, { size: "sm", disabled: connecting, onClick: () => void serial.connect({ baudRate: Number(baud) }), children: [connecting ? _jsx(Spinner, {}) : _jsx(Plug, {}), connecting ? 'Connecting…' : 'Connect'] })] })) })] }), _jsxs(NativeCapabilityPanelContent, { className: "space-y-3", children: [nativePortChoices.length > 0 ? (_jsxs("div", { "data-slot": "serial-console-port-chooser", className: "bg-muted/30 rounded-container space-y-2 border p-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-ui-caption font-medium", children: "Choose a serial port" }), _jsx(Button, { size: "xs", variant: "ghost", onClick: cancelNativePortSelection, children: "Cancel" })] }), _jsx("div", { className: "grid gap-1.5", children: nativePortChoices.map((choice, index) => (_jsxs(Button, { size: "sm", variant: "outline", className: "justify-start font-mono", onClick: () => chooseNativePort(choice), children: [_jsx(Cable, {}), " ", formatSerialPortLabel(choice.getInfo())] }, `${formatSerialPortLabel(choice.getInfo())}-${index}`))) })] })) : null, serial.error ? (_jsx("p", { className: "text-status-error text-ui-caption", children: serial.error.message })) : null, _jsx(StreamLog, { entries: serial.entries, maxHeight: 260, emptyLabel: connected ? 'Waiting for data' : 'Connect a port to start streaming' }), _jsxs("form", { "data-slot": "serial-console-composer", className: "flex items-center gap-2", onSubmit: submitLine, children: [_jsx(Input, { value: draft, onChange: (event) => setDraft(event.target.value), placeholder: "Send a line\u2026", disabled: !connected, spellCheck: false, autoComplete: "off", className: "text-ui-caption h-8 flex-1 font-mono" }), _jsx(Button, { type: "submit", size: "icon-sm", variant: "outline", disabled: !connected, "aria-label": "Send line", children: _jsx(CornerDownLeft, {}) })] })] }), _jsxs(NativeCapabilityPanelFooter, { className: "flex-wrap", children: [_jsxs("label", { "data-slot": "serial-console-signal", className: "flex items-center gap-1.5", children: [_jsx(Switch, { size: "sm", checked: serial.signals.dataTerminalReady, disabled: !connected, onCheckedChange: (checked) => void serial.setSignals({ dataTerminalReady: checked }), "aria-label": "Data terminal ready" }), _jsx("span", { className: "text-11 font-medium uppercase tracking-wider", children: "DTR" })] }), _jsxs("label", { "data-slot": "serial-console-signal", className: "flex items-center gap-1.5", children: [_jsx(Switch, { size: "sm", checked: serial.signals.requestToSend, disabled: !connected, onCheckedChange: (checked) => void serial.setSignals({ requestToSend: checked }), "aria-label": "Request to send" }), _jsx("span", { className: "text-11 font-medium uppercase tracking-wider", children: "RTS" })] }), _jsxs("label", { "data-slot": "serial-console-signal", className: "flex items-center gap-1.5", children: [_jsx(Switch, { size: "sm", checked: serial.signals.break, disabled: !connected, onCheckedChange: (checked) => void serial.setSignals({ break: checked }), "aria-label": "Break signal" }), _jsx("span", { className: "text-11 font-medium uppercase tracking-wider", children: "BRK" })] }), _jsx(Button, { size: "icon-xs", variant: "ghost", disabled: !connected, onClick: () => void serial.refreshSignals(), "aria-label": "Refresh input signals", title: "Refresh input signals", children: _jsx(RefreshCw, {}) }), serial.inputSignals ? (_jsxs("span", { "data-slot": "serial-console-input-signals", className: "text-11 font-mono tabular-nums", children: ["CTS ", serial.inputSignals.clearToSend ? '1' : '0', " \u00B7 DCD", ' ', serial.inputSignals.dataCarrierDetect ? '1' : '0', " \u00B7 DSR", ' ', serial.inputSignals.dataSetReady ? '1' : '0', " \u00B7 RI", ' ', serial.inputSignals.ringIndicator ? '1' : '0'] })) : null, retainedPort ? (_jsxs(Button, { size: "xs", variant: "ghost", onClick: () => void serial.forget(), children: [_jsx(ShieldX, {}), " Forget"] })) : null, _jsxs("span", { "data-slot": "serial-console-counters", className: "ml-auto shrink-0 font-mono tabular-nums", children: ["RX ", serial.rxBytes, " \u00B7 TX ", serial.txBytes] })] })] }));
398
398
  }
399
399
  export { SerialConsole };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { type MoldableGlobalShortcutEvent, type MoldableGlobalShortcutHandler } from '../../lib/native-capabilities';
2
+ import { type MoldableGlobalShortcutEvent, type MoldableGlobalShortcutHandler } from '../../lib/native-capabilities/index.js';
3
3
  /**
4
4
  * Splits an Electron-style accelerator ("CommandOrControl+Shift+K") into
5
5
  * display keys for `Kbd` chips — ['⌘', '⇧', 'K'] on macOS, ['Ctrl', 'Shift',
@@ -2,10 +2,10 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { X } from 'lucide-react';
4
4
  import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { isMoldableGlobalShortcut, registerMoldableGlobalShortcut, } from '../../lib/native-capabilities';
6
- import { cn } from '../../lib/utils';
7
- import { Button } from '../ui/button';
8
- import { Kbd, KbdGroup } from '../ui/kbd';
5
+ import { isMoldableGlobalShortcut, registerMoldableGlobalShortcut, } from '../../lib/native-capabilities/index.js';
6
+ import { cn } from '../../lib/utils.js';
7
+ import { Button } from '../ui/button.js';
8
+ import { Kbd, KbdGroup } from '../ui/kbd.js';
9
9
  function isApplePlatform() {
10
10
  if (typeof navigator === 'undefined')
11
11
  return false;
@@ -212,6 +212,6 @@ function ShortcutRecorder({ value, defaultValue = null, onChange, onTrigger, dis
212
212
  ? 'Recording shortcut, press keys'
213
213
  : shortcut
214
214
  ? `Shortcut ${shortcut}, click to re-record`
215
- : 'Record shortcut', onClick: () => setRecording(true), onBlur: () => setRecording(false), className: cn('border-input dark:bg-input/30 shadow-xs flex h-9 w-full min-w-0 items-center gap-2 rounded-md border bg-transparent px-3 text-left text-sm outline-none transition-[color,box-shadow]', 'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]', recording && 'border-ring ring-ring/50 ring-[3px]', disabled && 'pointer-events-none cursor-not-allowed opacity-50', shortcut && !recording && 'pr-9'), children: recording ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "relative flex size-1.5 shrink-0", children: [_jsx("span", { className: "bg-destructive absolute inline-flex h-full w-full animate-ping rounded-full opacity-75 motion-reduce:animate-none" }), _jsx("span", { className: "bg-destructive relative inline-flex size-1.5 rounded-full" })] }), _jsx("span", { className: "text-muted-foreground", children: "Press keys\u2026" })] })) : keys.length > 0 ? (_jsx(KbdGroup, { "data-state": pulse ? 'triggered' : 'idle', className: "origin-left transition-transform duration-150 data-[state=triggered]:scale-110 motion-reduce:transition-none", children: keys.map((key, index) => (_jsx(Kbd, { children: key }, `${index}-${key}`))) })) : (_jsx("span", { className: "text-muted-foreground", children: "Click to record" })) }), shortcut && !recording ? (_jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": "Clear shortcut", disabled: disabled, className: "absolute right-1.5", onClick: () => commit(null), children: _jsx(X, {}) })) : null] }), error ? (_jsx("p", { "data-slot": "shortcut-recorder-error", className: "text-status-error mt-1.5 text-xs", children: error.message })) : null] }));
215
+ : 'Record shortcut', onClick: () => setRecording(true), onBlur: () => setRecording(false), className: cn('border-input dark:bg-input/30 shadow-xs rounded-control text-ui-body flex h-control-md w-full min-w-0 items-center gap-control-gap border bg-transparent px-control-inline text-left outline-none transition-[color,box-shadow]', 'focus-visible:border-ring focus-visible:ring-ring focus-visible:ring-1', recording && 'border-ring ring-ring ring-2', disabled && 'pointer-events-none cursor-not-allowed opacity-50', shortcut && !recording && 'pr-9'), children: recording ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "relative flex size-1.5 shrink-0", children: [_jsx("span", { className: "bg-destructive rounded-pill absolute inline-flex h-full w-full animate-ping opacity-75 motion-reduce:animate-none" }), _jsx("span", { className: "bg-destructive rounded-pill relative inline-flex size-1.5" })] }), _jsx("span", { className: "text-muted-foreground", children: "Press keys\u2026" })] })) : keys.length > 0 ? (_jsx(KbdGroup, { "data-state": pulse ? 'triggered' : 'idle', className: "origin-left transition-transform duration-150 data-[state=triggered]:scale-110 motion-reduce:transition-none", children: keys.map((key, index) => (_jsx(Kbd, { children: key }, `${index}-${key}`))) })) : (_jsx("span", { className: "text-muted-foreground", children: "Click to record" })) }), shortcut && !recording ? (_jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": "Clear shortcut", disabled: disabled, className: "absolute right-1.5", onClick: () => commit(null), children: _jsx(X, {}) })) : null] }), error ? (_jsx("p", { "data-slot": "shortcut-recorder-error", className: "text-status-error text-ui-caption mt-1.5", children: error.message })) : null] }));
216
216
  }
217
217
  export { ShortcutRecorder };
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useRef, useState } from 'react';
4
- import { cn } from '../../lib/utils';
4
+ import { cn } from '../../lib/utils.js';
5
5
  /** Rolling entry buffer for `StreamLog`, capped at `maxEntries`. */
6
6
  export function useStreamLog(maxEntries = 500) {
7
7
  const [entries, setEntries] = useState([]);
@@ -57,9 +57,9 @@ function StreamLog({ entries, maxHeight = 240, emptyLabel = 'Waiting for data',
57
57
  const element = event.currentTarget;
58
58
  pinnedRef.current =
59
59
  element.scrollHeight - element.scrollTop - element.clientHeight < 32;
60
- }, className: cn('bg-muted/30 overflow-y-auto rounded-lg border font-mono text-xs', className), style: { maxHeight, ...props.style }, ...props, children: entries.length === 0 ? (_jsx("div", { className: "text-muted-foreground/70 flex items-center justify-center px-4 py-10", children: emptyLabel })) : (entries.map((entry) => {
60
+ }, className: cn('bg-muted/30 rounded-container text-ui-caption overflow-y-auto border font-mono', className), style: { maxHeight, ...props.style }, ...props, children: entries.length === 0 ? (_jsx("div", { className: "text-muted-foreground/70 flex items-center justify-center px-4 py-10", children: emptyLabel })) : (entries.map((entry) => {
61
61
  const direction = entry.direction ?? 'info';
62
- return (_jsxs("div", { "data-slot": "stream-log-entry", "data-direction": direction, className: "animate-in fade-in border-border/40 flex items-baseline gap-2 border-b px-3 py-1.5 duration-200 last:border-0 motion-reduce:animate-none", children: [!hideTimestamps && entry.timestamp !== undefined ? (_jsx("span", { className: "text-muted-foreground/70 shrink-0 text-[10px] tabular-nums", children: formatStreamLogTime(entry.timestamp) })) : null, _jsx("span", { className: cn('w-8 shrink-0 rounded border text-center text-[9px] font-semibold uppercase leading-4 tracking-wide', DIRECTION_CLASS[direction]), children: entry.label ?? DIRECTION_LABEL[direction] }), _jsx("span", { className: "min-w-0 flex-1 whitespace-pre-wrap break-all", children: entry.data })] }, entry.id));
62
+ return (_jsxs("div", { "data-slot": "stream-log-entry", "data-direction": direction, className: "animate-in fade-in border-border/40 flex items-baseline gap-2 border-b px-3 py-1.5 duration-200 last:border-0 motion-reduce:animate-none", children: [!hideTimestamps && entry.timestamp !== undefined ? (_jsx("span", { className: "text-muted-foreground/70 text-11 shrink-0 tabular-nums", children: formatStreamLogTime(entry.timestamp) })) : null, _jsx("span", { className: cn('rounded-control text-11 w-8 shrink-0 border text-center font-semibold uppercase leading-4 tracking-wide', DIRECTION_CLASS[direction]), children: entry.label ?? DIRECTION_LABEL[direction] }), _jsx("span", { className: "min-w-0 flex-1 whitespace-pre-wrap break-all", children: entry.data })] }, entry.id));
63
63
  })) }));
64
64
  }
65
65
  export { StreamLog, formatStreamLogTime };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { type MoldableSystemAudioCaptureMode, type MoldableSystemAudioEvent } from '../../lib/native-capabilities';
2
+ import { type MoldableSystemAudioCaptureMode, type MoldableSystemAudioEvent } from '../../lib/native-capabilities/index.js';
3
3
  export type MoldableSystemAudioMonitorStatus = 'idle' | 'starting' | 'stopping' | 'capturing' | 'error';
4
4
  export interface UseMoldableSystemAudioOptions {
5
5
  /** Observe raw capture events (lifecycle plus PCM data frames). */
@@ -2,15 +2,15 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { Play, Square, Volume2, VolumeX } from 'lucide-react';
4
4
  import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { startMoldableSystemAudioCapture, stopMoldableSystemAudioCapture, subscribeMoldableSystemAudioEvents, } from '../../lib/native-capabilities';
6
- import { Button } from '../ui/button';
7
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select';
8
- import { Spinner } from '../ui/spinner';
9
- import { CapabilityBadge } from './capability-badge';
10
- import { LiveIndicator } from './live-indicator';
11
- import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel';
12
- import { StreamLog, useStreamLog } from './stream-log';
13
- import { useMoldableCapability } from './use-capability';
5
+ import { startMoldableSystemAudioCapture, stopMoldableSystemAudioCapture, subscribeMoldableSystemAudioEvents, } from '../../lib/native-capabilities/index.js';
6
+ import { Button } from '../ui/button.js';
7
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select.js';
8
+ import { Spinner } from '../ui/spinner.js';
9
+ import { CapabilityBadge } from './capability-badge.js';
10
+ import { LiveIndicator } from './live-indicator.js';
11
+ import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel.js';
12
+ import { StreamLog, useStreamLog } from './stream-log.js';
13
+ import { useMoldableCapability } from './use-capability.js';
14
14
  const SYSTEM_AUDIO_SAMPLE_RATE = 48_000;
15
15
  const FRAME_LOG_INTERVAL = 50;
16
16
  function computeRmsLevel(buffer) {
@@ -254,7 +254,7 @@ function SystemAudioMonitor({ className, defaultMode = 'systemAudio', ...props }
254
254
  const unsupported = capability.status === 'unsupported' || capability.status === 'unavailable';
255
255
  return (_jsxs(NativeCapabilityPanel, { "data-slot": "system-audio-monitor", "data-status": audio.status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(Volume2, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "System Audio" }), _jsx(CapabilityBadge, { capability: "system-audio" }), !unsupported ? (_jsxs(NativeCapabilityPanelAction, { children: [_jsxs(Select, { value: selectedMode, onValueChange: (value) => setSelectedMode(value === 'systemMicrophone'
256
256
  ? 'systemMicrophone'
257
- : 'systemAudio'), disabled: starting || stopping || capturing, children: [_jsx(SelectTrigger, { size: "sm", className: "text-xs", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "systemAudio", children: MODE_LABEL.systemAudio }), _jsx(SelectItem, { value: "systemMicrophone", children: MODE_LABEL.systemMicrophone })] })] }), _jsxs(Button, { size: "sm", variant: capturing ? 'outline' : 'default', disabled: starting || stopping, onClick: () => {
257
+ : 'systemAudio'), disabled: starting || stopping || capturing, children: [_jsx(SelectTrigger, { size: "sm", className: "text-ui-caption", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "systemAudio", children: MODE_LABEL.systemAudio }), _jsx(SelectItem, { value: "systemMicrophone", children: MODE_LABEL.systemMicrophone })] })] }), _jsxs(Button, { size: "sm", variant: capturing ? 'outline' : 'default', disabled: starting || stopping, onClick: () => {
258
258
  if (capturing) {
259
259
  void audio.stop();
260
260
  }
@@ -268,8 +268,8 @@ function SystemAudioMonitor({ className, defaultMode = 'systemAudio', ...props }
268
268
  ? 'Stopping…'
269
269
  : capturing
270
270
  ? 'Stop'
271
- : 'Start'] })] })) : null] }), _jsx(NativeCapabilityPanelContent, { className: "space-y-3", children: unsupported ? (_jsxs("div", { className: "animate-in fade-in flex flex-col items-center gap-3 py-6 text-center duration-300 motion-reduce:animate-none", children: [_jsx("div", { className: "text-muted-foreground bg-background shadow-xs flex size-10 items-center justify-center rounded-lg border [&_svg]:size-5", children: _jsx(VolumeX, {}) }), _jsx("p", { className: "text-sm font-medium", children: "System audio unavailable" }), _jsx("p", { className: "text-muted-foreground max-w-64 text-xs", children: capability.status === 'unavailable'
271
+ : 'Start'] })] })) : null] }), _jsx(NativeCapabilityPanelContent, { className: "space-y-3", children: unsupported ? (_jsxs("div", { className: "animate-in fade-in flex flex-col items-center gap-3 py-6 text-center duration-300 motion-reduce:animate-none", children: [_jsx("div", { className: "text-muted-foreground bg-background shadow-xs rounded-container flex size-10 items-center justify-center border [&_svg]:size-5", children: _jsx(VolumeX, {}) }), _jsx("p", { className: "text-ui-body font-medium", children: "System audio unavailable" }), _jsx("p", { className: "text-muted-foreground text-ui-caption max-w-64", children: capability.status === 'unavailable'
272
272
  ? 'System audio capture is only available inside Moldable.'
273
- : 'System audio capture requires Moldable on macOS.' })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "bg-muted relative h-2 flex-1 overflow-hidden rounded-full", children: [_jsx("div", { className: "bg-primary absolute inset-y-0 left-0 rounded-full transition-[width] duration-100 ease-out motion-reduce:transition-none", style: { width: `${Math.min(1, level) * 100}%` } }), peak > 0 ? (_jsx("div", { className: "bg-primary/70 absolute inset-y-0 w-0.5 rounded-full transition-[left] duration-150 ease-out motion-reduce:transition-none", style: { left: `calc(${Math.min(1, peak) * 100}% - 2px)` } })) : null] }), capturing ? _jsx(LiveIndicator, { label: "Capturing" }) : null] }), audio.status === 'error' ? (_jsx("p", { className: "text-status-error text-xs", children: audio.error?.message ?? 'System audio capture failed.' })) : null, _jsx(StreamLog, { entries: log.entries, maxHeight: 180, emptyLabel: "No capture events yet" })] })) }), _jsxs(NativeCapabilityPanelFooter, { children: [_jsx("span", { className: "truncate", children: audio.mode ? MODE_LABEL[audio.mode] : 'No capture yet' }), _jsxs("span", { className: "ml-auto shrink-0 font-mono tabular-nums", children: [SYSTEM_AUDIO_SAMPLE_RATE.toLocaleString(), " Hz"] }), _jsxs("span", { className: "shrink-0 font-mono tabular-nums", children: [audio.framesReceived.toLocaleString(), " frames"] })] })] }));
273
+ : 'System audio capture requires Moldable on macOS.' })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "bg-muted rounded-pill relative h-2 flex-1 overflow-hidden", children: [_jsx("div", { className: "bg-primary rounded-pill absolute inset-y-0 left-0 transition-[width] duration-100 ease-out motion-reduce:transition-none", style: { width: `${Math.min(1, level) * 100}%` } }), peak > 0 ? (_jsx("div", { className: "bg-primary/70 rounded-pill absolute inset-y-0 w-0.5 transition-[left] duration-150 ease-out motion-reduce:transition-none", style: { left: `calc(${Math.min(1, peak) * 100}% - 2px)` } })) : null] }), capturing ? _jsx(LiveIndicator, { label: "Capturing" }) : null] }), audio.status === 'error' ? (_jsx("p", { className: "text-status-error text-ui-caption", children: audio.error?.message ?? 'System audio capture failed.' })) : null, _jsx(StreamLog, { entries: log.entries, maxHeight: 180, emptyLabel: "No capture events yet" })] })) }), _jsxs(NativeCapabilityPanelFooter, { children: [_jsx("span", { className: "truncate", children: audio.mode ? MODE_LABEL[audio.mode] : 'No capture yet' }), _jsxs("span", { className: "ml-auto shrink-0 font-mono tabular-nums", children: [SYSTEM_AUDIO_SAMPLE_RATE.toLocaleString(), " Hz"] }), _jsxs("span", { className: "shrink-0 font-mono tabular-nums", children: [audio.framesReceived.toLocaleString(), " frames"] })] })] }));
274
274
  }
275
275
  export { SystemAudioMonitor };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { type MoldableUsbControlTransferParameters, type MoldableUsbDevice, type MoldableUsbDeviceFilter, type MoldableUsbOpenOptions, type MoldableUsbRequestOptions } from '../../lib/native-capabilities';
2
+ import { type MoldableUsbControlTransferParameters, type MoldableUsbDevice, type MoldableUsbDeviceFilter, type MoldableUsbOpenOptions, type MoldableUsbRequestOptions } from '../../lib/native-capabilities/index.js';
3
3
  export type MoldableUsbStatus = 'idle' | 'loading' | 'requesting' | 'error';
4
4
  export interface UseMoldableUsbOptions {
5
5
  /** Device filters used when `request` does not override them. */
@@ -29,10 +29,10 @@ export declare function useMoldableUsb(options?: UseMoldableUsbOptions): {
29
29
  open: (device: MoldableUsbDevice) => Promise<void>;
30
30
  close: (device: MoldableUsbDevice) => Promise<boolean>;
31
31
  forget: (device: MoldableUsbDevice) => Promise<boolean>;
32
- readEndpoint: (device: MoldableUsbDevice, endpoint: number, length: number) => Promise<import("../..").MoldableUsbInTransferResult>;
33
- writeEndpoint: (device: MoldableUsbDevice, endpoint: number, data: BufferSource) => Promise<import("../..").MoldableUsbOutTransferResult>;
34
- readControl: (device: MoldableUsbDevice, setup: MoldableUsbControlTransferParameters, length: number) => Promise<import("../..").MoldableUsbInTransferResult>;
35
- writeControl: (device: MoldableUsbDevice, setup: MoldableUsbControlTransferParameters, data?: BufferSource) => Promise<import("../..").MoldableUsbOutTransferResult>;
32
+ readEndpoint: (device: MoldableUsbDevice, endpoint: number, length: number) => Promise<import("../../index.js").MoldableUsbInTransferResult>;
33
+ writeEndpoint: (device: MoldableUsbDevice, endpoint: number, data: BufferSource) => Promise<import("../../index.js").MoldableUsbOutTransferResult>;
34
+ readControl: (device: MoldableUsbDevice, setup: MoldableUsbControlTransferParameters, length: number) => Promise<import("../../index.js").MoldableUsbInTransferResult>;
35
+ writeControl: (device: MoldableUsbDevice, setup: MoldableUsbControlTransferParameters, data?: BufferSource) => Promise<import("../../index.js").MoldableUsbOutTransferResult>;
36
36
  clearHalt: (device: MoldableUsbDevice, direction: "in" | "out", endpoint: number) => Promise<void>;
37
37
  reset: (device: MoldableUsbDevice) => Promise<void>;
38
38
  };
@@ -2,16 +2,16 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { RefreshCw, RotateCcw, Trash2, Usb } from 'lucide-react';
4
4
  import { useCallback, useEffect, useRef, useState } from 'react';
5
- import { NativeCapabilityBridgeError, clearMoldableUsbHalt, closeMoldableUsbDevice, forgetMoldableUsbDevice, getMoldableUsbDevices, openMoldableUsbDevice, readMoldableUsbControlTransfer, readMoldableUsbEndpoint, requestMoldableUsbDevice, resetMoldableUsbDevice, writeMoldableUsbControlTransfer, writeMoldableUsbEndpoint, } from '../../lib/native-capabilities';
6
- import { Button } from '../ui/button';
7
- import { Input } from '../ui/input';
8
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select';
9
- import { Spinner } from '../ui/spinner';
10
- import { CapabilityBadge } from './capability-badge';
11
- import { formatHexBytes, parseHexBytes, parseIntegerInput, } from './device-io-controls';
12
- import { DeviceList, DeviceListEmpty, DeviceListItem } from './device-list';
13
- import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel';
14
- import { Readout, ReadoutItem } from './readout';
5
+ import { NativeCapabilityBridgeError, clearMoldableUsbHalt, closeMoldableUsbDevice, forgetMoldableUsbDevice, getMoldableUsbDevices, openMoldableUsbDevice, readMoldableUsbControlTransfer, readMoldableUsbEndpoint, requestMoldableUsbDevice, resetMoldableUsbDevice, writeMoldableUsbControlTransfer, writeMoldableUsbEndpoint, } from '../../lib/native-capabilities/index.js';
6
+ import { Button } from '../ui/button.js';
7
+ import { Input } from '../ui/input.js';
8
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select.js';
9
+ import { Spinner } from '../ui/spinner.js';
10
+ import { CapabilityBadge } from './capability-badge.js';
11
+ import { formatHexBytes, parseHexBytes, parseIntegerInput, } from './device-io-controls.js';
12
+ import { DeviceList, DeviceListEmpty, DeviceListItem } from './device-list.js';
13
+ import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel.js';
14
+ import { Readout, ReadoutItem } from './readout.js';
15
15
  function toError(cause) {
16
16
  return cause instanceof Error ? cause : new Error(String(cause));
17
17
  }
@@ -309,7 +309,7 @@ function UsbDeviceControls({ device, usb }) {
309
309
  value: parseIntegerInput(value, 'Value', 0, 65_535),
310
310
  index: parseIntegerInput(index, 'Index', 0, 65_535),
311
311
  });
312
- return (_jsxs("div", { "data-slot": "usb-device-controls", className: "bg-muted/30 mt-2 space-y-3 rounded-md border p-2.5", children: [_jsxs("div", { className: "grid gap-2 sm:grid-cols-3", children: [_jsx(Input, { "aria-label": "USB endpoint number", value: endpoint, onChange: (event) => setEndpoint(event.target.value), placeholder: "Endpoint", className: "h-8 font-mono text-xs" }), _jsx(Input, { "aria-label": "USB transfer length", value: length, onChange: (event) => setLength(event.target.value), placeholder: "Length", className: "h-8 font-mono text-xs" }), _jsx(Input, { "aria-label": "USB endpoint payload", value: payload, onChange: (event) => setPayload(event.target.value), placeholder: "Hex payload", className: "h-8 font-mono text-xs" })] }), _jsxs("div", { className: "flex flex-wrap gap-1.5", children: [_jsx(Button, { size: "xs", variant: "outline", disabled: busy, onClick: () => void run(async () => {
312
+ return (_jsxs("div", { "data-slot": "usb-device-controls", className: "bg-muted/30 rounded-control mt-2 space-y-3 border p-2.5", children: [_jsxs("div", { className: "grid gap-2 sm:grid-cols-3", children: [_jsx(Input, { "aria-label": "USB endpoint number", value: endpoint, onChange: (event) => setEndpoint(event.target.value), placeholder: "Endpoint", className: "text-ui-caption h-8 font-mono" }), _jsx(Input, { "aria-label": "USB transfer length", value: length, onChange: (event) => setLength(event.target.value), placeholder: "Length", className: "text-ui-caption h-8 font-mono" }), _jsx(Input, { "aria-label": "USB endpoint payload", value: payload, onChange: (event) => setPayload(event.target.value), placeholder: "Hex payload", className: "text-ui-caption h-8 font-mono" })] }), _jsxs("div", { className: "flex flex-wrap gap-1.5", children: [_jsx(Button, { size: "xs", variant: "outline", disabled: busy, onClick: () => void run(async () => {
313
313
  const transfer = await usb.readEndpoint(device, endpointNumber(), transferLength());
314
314
  return `Endpoint IN · ${transfer.status} · ${formatHexBytes(transfer.data)}`;
315
315
  }), children: "Endpoint IN" }), _jsx(Button, { size: "xs", variant: "outline", disabled: busy, onClick: () => void run(async () => {
@@ -325,7 +325,7 @@ function UsbDeviceControls({ device, usb }) {
325
325
  ['Request', request, setRequest],
326
326
  ['Value', value, setValue],
327
327
  ['Index', index, setIndex],
328
- ].map(([label, current, update]) => (_jsx(Input, { "aria-label": `USB control ${String(label).toLowerCase()}`, value: current, onChange: (event) => update(event.target.value), placeholder: label, className: "h-8 font-mono text-xs" }, label)))] }), _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx(Button, { size: "xs", variant: "outline", disabled: busy, onClick: () => void run(async () => {
328
+ ].map(([label, current, update]) => (_jsx(Input, { "aria-label": `USB control ${String(label).toLowerCase()}`, value: current, onChange: (event) => update(event.target.value), placeholder: label, className: "text-ui-caption h-8 font-mono" }, label)))] }), _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx(Button, { size: "xs", variant: "outline", disabled: busy, onClick: () => void run(async () => {
329
329
  const transfer = await usb.readControl(device, setup(), transferLength());
330
330
  return `Control IN · ${transfer.status} · ${formatHexBytes(transfer.data)}`;
331
331
  }), children: "Control IN" }), _jsx(Button, { size: "xs", variant: "outline", disabled: busy, onClick: () => void run(async () => {
@@ -334,7 +334,7 @@ function UsbDeviceControls({ device, usb }) {
334
334
  }), children: "Control OUT" }), _jsxs(Button, { size: "xs", variant: "ghost", disabled: busy, onClick: () => void run(async () => {
335
335
  await usb.reset(device);
336
336
  return 'Device reset';
337
- }), children: [_jsx(RotateCcw, {}), "Reset"] }), _jsx("span", { className: "text-muted-foreground ml-auto truncate font-mono text-[10px]", children: busy ? 'Working…' : result })] })] }));
337
+ }), children: [_jsx(RotateCcw, {}), "Reset"] }), _jsx("span", { className: "text-muted-foreground text-11 ml-auto truncate font-mono", children: busy ? 'Working…' : result })] })] }));
338
338
  }
339
339
  /**
340
340
  * USB device panel: request access, list granted devices, open/close each
@@ -349,13 +349,13 @@ function UsbDevicePanel({ className, filters, selectNativeDevice, openOptions, o
349
349
  });
350
350
  const requesting = usb.status === 'requesting';
351
351
  const loading = usb.status === 'loading';
352
- return (_jsxs(NativeCapabilityPanel, { "data-slot": "usb-device-panel", "data-status": usb.status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(Usb, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "USB" }), _jsx(CapabilityBadge, { capability: "usb" }), _jsxs(NativeCapabilityPanelAction, { children: [_jsxs(Button, { size: "sm", disabled: requesting, onClick: () => void usb.request(), children: [requesting ? _jsx(Spinner, {}) : _jsx(Usb, {}), requesting ? 'Requesting…' : 'Request device'] }), _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Refresh devices", disabled: loading || requesting, onClick: () => void usb.refresh(), children: _jsx(RefreshCw, { className: loading ? 'animate-spin motion-reduce:animate-none' : undefined }) })] })] }), _jsxs(NativeCapabilityPanelContent, { children: [usb.nativeDeviceChoices.length > 0 ? (_jsxs("div", { "data-slot": "usb-native-device-picker", className: "bg-muted/30 mb-4 space-y-2 rounded-lg border p-3", children: [_jsx("p", { className: "text-sm font-medium", children: "Choose a USB device" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "More than one native device matched. Select the device explicitly." }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [usb.nativeDeviceChoices.map((device, index) => (_jsxs(Button, { size: "xs", variant: "outline", onClick: () => usb.selectNativeDevice(device), children: [device.productName || 'USB device', " \u00B7", ' ', formatHexId(device.vendorId), ":", formatHexId(device.productId)] }, `${usbDeviceDescriptionId(device)}:${index}`))), _jsx(Button, { size: "xs", variant: "ghost", onClick: usb.cancelNativeSelection, children: "Cancel" })] })] })) : null, _jsx(DeviceList, { children: usb.devices.length === 0 ? (_jsxs(DeviceListEmpty, { icon: _jsx(Usb, {}), children: [_jsx("span", { className: "font-medium", children: "No devices yet" }), _jsx("span", { className: "text-muted-foreground/70 text-xs", children: "Request access to a USB device to get started." })] })) : (usb.devices.map((device, index) => {
352
+ return (_jsxs(NativeCapabilityPanel, { "data-slot": "usb-device-panel", "data-status": usb.status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(Usb, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "USB" }), _jsx(CapabilityBadge, { capability: "usb" }), _jsxs(NativeCapabilityPanelAction, { children: [_jsxs(Button, { size: "sm", disabled: requesting, onClick: () => void usb.request(), children: [requesting ? _jsx(Spinner, {}) : _jsx(Usb, {}), requesting ? 'Requesting…' : 'Request device'] }), _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Refresh devices", disabled: loading || requesting, onClick: () => void usb.refresh(), children: _jsx(RefreshCw, { className: loading ? 'animate-spin motion-reduce:animate-none' : undefined }) })] })] }), _jsxs(NativeCapabilityPanelContent, { children: [usb.nativeDeviceChoices.length > 0 ? (_jsxs("div", { "data-slot": "usb-native-device-picker", className: "bg-muted/30 rounded-container mb-4 space-y-2 border p-3", children: [_jsx("p", { className: "text-ui-body font-medium", children: "Choose a USB device" }), _jsx("p", { className: "text-muted-foreground text-ui-caption", children: "More than one native device matched. Select the device explicitly." }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [usb.nativeDeviceChoices.map((device, index) => (_jsxs(Button, { size: "xs", variant: "outline", onClick: () => usb.selectNativeDevice(device), children: [device.productName || 'USB device', " \u00B7", ' ', formatHexId(device.vendorId), ":", formatHexId(device.productId)] }, `${usbDeviceDescriptionId(device)}:${index}`))), _jsx(Button, { size: "xs", variant: "ghost", onClick: usb.cancelNativeSelection, children: "Cancel" })] })] })) : null, _jsx(DeviceList, { children: usb.devices.length === 0 ? (_jsxs(DeviceListEmpty, { icon: _jsx(Usb, {}), children: [_jsx("span", { className: "font-medium", children: "No devices yet" }), _jsx("span", { className: "text-muted-foreground/70 text-ui-caption", children: "Request access to a USB device to get started." })] })) : (usb.devices.map((device, index) => {
353
353
  const id = usb.deviceId(device);
354
354
  const open = usb.openDeviceIds.includes(id) || device.opened;
355
355
  return (_jsx(DeviceListItem, { icon: _jsx(Usb, {}), name: device.productName || 'USB device', description: `${formatHexId(device.vendorId)}:${formatHexId(device.productId)}` +
356
356
  (device.manufacturerName
357
357
  ? ` · ${device.manufacturerName}`
358
- : ''), connected: open, action: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { size: "xs", variant: "outline", onClick: () => void (open ? usb.close(device) : usb.open(device)), children: open ? 'Close' : 'Open' }), _jsx(Button, { size: "icon-xs", variant: "ghost", "aria-label": `Forget ${device.productName || 'USB device'}`, onClick: () => void usb.forget(device), children: _jsx(Trash2, {}) })] }), children: open ? (_jsxs("div", { "data-slot": "usb-device-details", className: "animate-in fade-in slide-in-from-top-1 bg-muted/30 mt-2 rounded-md border p-2.5 duration-200 motion-reduce:animate-none", children: [_jsxs(Readout, { className: "gap-y-2 sm:grid-cols-4", children: [_jsx(ReadoutItem, { label: "Configuration", value: device.configuration?.configurationValue ?? null }), _jsx(ReadoutItem, { label: "Vendor ID", value: formatHexId(device.vendorId) }), _jsx(ReadoutItem, { label: "Product ID", value: formatHexId(device.productId) }), _jsx(ReadoutItem, { label: "Serial", value: device.serialNumber ?? null })] }), _jsx(UsbDeviceControls, { device: device, usb: usb })] })) : null }, `${id}:${index}`));
358
+ : ''), connected: open, action: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Button, { size: "xs", variant: "outline", onClick: () => void (open ? usb.close(device) : usb.open(device)), children: open ? 'Close' : 'Open' }), _jsx(Button, { size: "icon-xs", variant: "ghost", "aria-label": `Forget ${device.productName || 'USB device'}`, onClick: () => void usb.forget(device), children: _jsx(Trash2, {}) })] }), children: open ? (_jsxs("div", { "data-slot": "usb-device-details", className: "animate-in fade-in slide-in-from-top-1 bg-muted/30 rounded-control mt-2 border p-2.5 duration-200 motion-reduce:animate-none", children: [_jsxs(Readout, { className: "gap-y-2 sm:grid-cols-4", children: [_jsx(ReadoutItem, { label: "Configuration", value: device.configuration?.configurationValue ?? null }), _jsx(ReadoutItem, { label: "Vendor ID", value: formatHexId(device.vendorId) }), _jsx(ReadoutItem, { label: "Product ID", value: formatHexId(device.productId) }), _jsx(ReadoutItem, { label: "Serial", value: device.serialNumber ?? null })] }), _jsx(UsbDeviceControls, { device: device, usb: usb })] })) : null }, `${id}:${index}`));
359
359
  })) })] }), _jsxs(NativeCapabilityPanelFooter, { children: [usb.error ? (_jsx("span", { className: "text-status-error truncate", children: usb.error.message })) : (_jsx("span", { className: "truncate", children: usb.devices.length === 0
360
360
  ? 'No devices authorized'
361
361
  : `${usb.devices.length} device${usb.devices.length === 1 ? '' : 's'} known` })), _jsxs("span", { className: "ml-auto shrink-0 font-mono tabular-nums", children: [usb.openDeviceIds.length, " open"] })] })] }));
@@ -1,4 +1,4 @@
1
- import { type NativeCapabilityDescriptor, type NativeCapabilityId, type NativeCapabilityManifest } from '../../lib/native-capabilities';
1
+ import { type NativeCapabilityDescriptor, type NativeCapabilityId, type NativeCapabilityManifest } from '../../lib/native-capabilities/index.js';
2
2
  export type MoldableCapabilityStatus = 'checking' | 'supported' | 'partial' | 'unsupported' | 'unavailable';
3
3
  /**
4
4
  * Loads the native capability manifest once per page and shares it across all
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { useCallback, useEffect, useRef, useState } from 'react';
3
- import { getMoldableNativeCapabilities, } from '../../lib/native-capabilities';
3
+ import { getMoldableNativeCapabilities, } from '../../lib/native-capabilities/index.js';
4
4
  let manifestPromise = null;
5
5
  /**
6
6
  * Loads the native capability manifest once per page and shares it across all