@moldable-ai/ui 0.2.21 → 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 (515) 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/catalog-types.d.ts +7 -0
  5. package/dist/catalog/catalog-types.d.ts.map +1 -1
  6. package/dist/catalog/catalog-types.js +1 -0
  7. package/dist/catalog/component-catalog.d.ts +1 -1
  8. package/dist/catalog/component-catalog.js +2 -2
  9. package/dist/catalog/core-catalog-exclusions.d.ts +1 -1
  10. package/dist/catalog/core-catalog-exclusions.d.ts.map +1 -1
  11. package/dist/catalog/core-catalog-exclusions.js +1 -146
  12. package/dist/catalog/core-catalog.d.ts +1 -1
  13. package/dist/catalog/core-catalog.d.ts.map +1 -1
  14. package/dist/catalog/core-catalog.js +11 -7
  15. package/dist/catalog/core-collection-stories.d.ts +1 -1
  16. package/dist/catalog/core-collection-stories.d.ts.map +1 -1
  17. package/dist/catalog/core-collection-stories.js +41 -9
  18. package/dist/catalog/core-control-stories.d.ts +1 -1
  19. package/dist/catalog/core-control-stories.d.ts.map +1 -1
  20. package/dist/catalog/core-control-stories.js +53 -22
  21. package/dist/catalog/core-feedback-stories.d.ts +1 -1
  22. package/dist/catalog/core-feedback-stories.d.ts.map +1 -1
  23. package/dist/catalog/core-feedback-stories.js +89 -10
  24. package/dist/catalog/core-form-stories.d.ts +3 -0
  25. package/dist/catalog/core-form-stories.d.ts.map +1 -0
  26. package/dist/catalog/core-form-stories.js +56 -0
  27. package/dist/catalog/core-foundation-stories.d.ts +1 -1
  28. package/dist/catalog/core-foundation-stories.js +7 -7
  29. package/dist/catalog/core-layout-stories.d.ts +3 -0
  30. package/dist/catalog/core-layout-stories.d.ts.map +1 -0
  31. package/dist/catalog/core-layout-stories.js +78 -0
  32. package/dist/catalog/core-navigation-stories.d.ts +1 -1
  33. package/dist/catalog/core-navigation-stories.d.ts.map +1 -1
  34. package/dist/catalog/core-navigation-stories.js +25 -3
  35. package/dist/catalog/core-overlay-stories.d.ts +1 -1
  36. package/dist/catalog/core-overlay-stories.d.ts.map +1 -1
  37. package/dist/catalog/core-overlay-stories.js +113 -8
  38. package/dist/catalog/index.d.ts +6 -6
  39. package/dist/catalog/index.js +6 -6
  40. package/dist/components/app-error-boundary.d.ts.map +1 -1
  41. package/dist/components/app-error-boundary.js +4 -3
  42. package/dist/components/chat/chat-image-lightbox.js +3 -3
  43. package/dist/components/chat/chat-input.js +5 -5
  44. package/dist/components/chat/chat-message.js +17 -17
  45. package/dist/components/chat/chat-messages.d.ts +1 -1
  46. package/dist/components/chat/chat-messages.js +3 -3
  47. package/dist/components/chat/chat-panel.d.ts +6 -6
  48. package/dist/components/chat/chat-panel.d.ts.map +1 -1
  49. package/dist/components/chat/chat-panel.js +33 -33
  50. package/dist/components/chat/checkpoint-badge.js +3 -3
  51. package/dist/components/chat/conversation-history.d.ts.map +1 -1
  52. package/dist/components/chat/conversation-history.js +13 -13
  53. package/dist/components/chat/index.d.ts +20 -15
  54. package/dist/components/chat/index.d.ts.map +1 -1
  55. package/dist/components/chat/index.js +20 -15
  56. package/dist/components/chat/markdown.js +1 -1
  57. package/dist/components/chat/model-effort-selector.js +10 -10
  58. package/dist/components/chat/model-selector.js +4 -4
  59. package/dist/components/chat/reasoning-effort-selector.js +4 -4
  60. package/dist/components/chat/restore-dialog.js +3 -3
  61. package/dist/components/chat/thinking-timeline.js +2 -2
  62. package/dist/components/chat/tool-approval.d.ts +1 -1
  63. package/dist/components/chat/tool-approval.d.ts.map +1 -1
  64. package/dist/components/chat/tool-approval.js +9 -9
  65. package/dist/components/chat/tool-handlers.d.ts +2 -2
  66. package/dist/components/chat/tool-handlers.js +90 -90
  67. package/dist/components/chat/voice-orb-audio.d.ts +16 -0
  68. package/dist/components/chat/voice-orb-audio.d.ts.map +1 -0
  69. package/dist/components/chat/voice-orb-audio.js +110 -0
  70. package/dist/components/chat/voice-orb-renderer.d.ts +51 -0
  71. package/dist/components/chat/voice-orb-renderer.d.ts.map +1 -0
  72. package/dist/components/chat/voice-orb-renderer.js +410 -0
  73. package/dist/components/chat/voice-orb-shaders.d.ts +3 -0
  74. package/dist/components/chat/voice-orb-shaders.d.ts.map +1 -0
  75. package/dist/components/chat/voice-orb-shaders.js +355 -0
  76. package/dist/components/chat/voice-orb-types.d.ts +24 -0
  77. package/dist/components/chat/voice-orb-types.d.ts.map +1 -0
  78. package/dist/components/chat/voice-orb-types.js +73 -0
  79. package/dist/components/chat/voice-orb.d.ts +20 -0
  80. package/dist/components/chat/voice-orb.d.ts.map +1 -0
  81. package/dist/components/chat/voice-orb.js +67 -0
  82. package/dist/components/code-block.js +1 -1
  83. package/dist/components/hardware/bluetooth-panel.d.ts +2 -2
  84. package/dist/components/hardware/bluetooth-panel.js +10 -10
  85. package/dist/components/hardware/camera-preview.js +6 -6
  86. package/dist/components/hardware/capability-badge.d.ts +2 -2
  87. package/dist/components/hardware/capability-badge.js +2 -2
  88. package/dist/components/hardware/capability-matrix.d.ts +1 -1
  89. package/dist/components/hardware/capability-matrix.js +5 -5
  90. package/dist/components/hardware/clipboard-button.d.ts +1 -1
  91. package/dist/components/hardware/clipboard-button.js +2 -2
  92. package/dist/components/hardware/device-list.js +1 -1
  93. package/dist/components/hardware/display-map.d.ts +1 -1
  94. package/dist/components/hardware/display-map.js +7 -7
  95. package/dist/components/hardware/haptic-button.d.ts +2 -2
  96. package/dist/components/hardware/haptic-button.js +3 -3
  97. package/dist/components/hardware/hardware-panel.js +1 -1
  98. package/dist/components/hardware/hid-panel.d.ts +2 -2
  99. package/dist/components/hardware/hid-panel.js +10 -10
  100. package/dist/components/hardware/index.d.ts +26 -26
  101. package/dist/components/hardware/index.js +26 -26
  102. package/dist/components/hardware/live-indicator.js +1 -1
  103. package/dist/components/hardware/local-auth-button.d.ts +2 -2
  104. package/dist/components/hardware/local-auth-button.js +4 -4
  105. package/dist/components/hardware/location-panel.d.ts +1 -1
  106. package/dist/components/hardware/location-panel.js +6 -6
  107. package/dist/components/hardware/microphone-meter.js +7 -7
  108. package/dist/components/hardware/midi-monitor.d.ts +2 -2
  109. package/dist/components/hardware/midi-monitor.js +9 -9
  110. package/dist/components/hardware/notification-panel.d.ts +1 -1
  111. package/dist/components/hardware/notification-panel.js +8 -8
  112. package/dist/components/hardware/power-blocker-controller.d.ts +1 -1
  113. package/dist/components/hardware/power-blocker-controller.js +1 -1
  114. package/dist/components/hardware/power-panel.d.ts +1 -1
  115. package/dist/components/hardware/power-panel.js +9 -9
  116. package/dist/components/hardware/readout.js +1 -1
  117. package/dist/components/hardware/screen-share-preview.js +5 -5
  118. package/dist/components/hardware/secure-storage-panel.d.ts +1 -1
  119. package/dist/components/hardware/secure-storage-panel.js +9 -9
  120. package/dist/components/hardware/serial-console.d.ts +2 -2
  121. package/dist/components/hardware/serial-console.js +10 -10
  122. package/dist/components/hardware/shortcut-recorder.d.ts +1 -1
  123. package/dist/components/hardware/shortcut-recorder.js +4 -4
  124. package/dist/components/hardware/stream-log.js +1 -1
  125. package/dist/components/hardware/system-audio-monitor.d.ts +1 -1
  126. package/dist/components/hardware/system-audio-monitor.js +9 -9
  127. package/dist/components/hardware/usb-panel.d.ts +5 -5
  128. package/dist/components/hardware/usb-panel.js +10 -10
  129. package/dist/components/hardware/use-capability.d.ts +1 -1
  130. package/dist/components/hardware/use-capability.js +1 -1
  131. package/dist/components/markdown.js +5 -5
  132. package/dist/components/native-capabilities/bluetooth-panel.d.ts +2 -2
  133. package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -1
  134. package/dist/components/native-capabilities/bluetooth-panel.js +17 -17
  135. package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -1
  136. package/dist/components/native-capabilities/camera-preview.js +7 -7
  137. package/dist/components/native-capabilities/capability-badge.d.ts +2 -2
  138. package/dist/components/native-capabilities/capability-badge.js +4 -4
  139. package/dist/components/native-capabilities/capability-matrix.d.ts +1 -1
  140. package/dist/components/native-capabilities/capability-matrix.js +7 -7
  141. package/dist/components/native-capabilities/clipboard-button.d.ts +1 -1
  142. package/dist/components/native-capabilities/clipboard-button.js +2 -2
  143. package/dist/components/native-capabilities/device-list.js +4 -4
  144. package/dist/components/native-capabilities/display-map.d.ts +1 -1
  145. package/dist/components/native-capabilities/display-map.d.ts.map +1 -1
  146. package/dist/components/native-capabilities/display-map.js +11 -11
  147. package/dist/components/native-capabilities/haptic-button.d.ts +2 -2
  148. package/dist/components/native-capabilities/haptic-button.js +3 -3
  149. package/dist/components/native-capabilities/hid-panel.d.ts +2 -2
  150. package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -1
  151. package/dist/components/native-capabilities/hid-panel.js +14 -14
  152. package/dist/components/native-capabilities/index.d.ts +26 -26
  153. package/dist/components/native-capabilities/index.js +26 -26
  154. package/dist/components/native-capabilities/live-indicator.js +3 -3
  155. package/dist/components/native-capabilities/local-auth-button.d.ts +2 -2
  156. package/dist/components/native-capabilities/local-auth-button.js +4 -4
  157. package/dist/components/native-capabilities/location-panel.d.ts +1 -1
  158. package/dist/components/native-capabilities/location-panel.d.ts.map +1 -1
  159. package/dist/components/native-capabilities/location-panel.js +8 -8
  160. package/dist/components/native-capabilities/microphone-meter.js +9 -9
  161. package/dist/components/native-capabilities/midi-monitor.d.ts +2 -2
  162. package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -1
  163. package/dist/components/native-capabilities/midi-monitor.js +11 -11
  164. package/dist/components/native-capabilities/native-capability-panel.js +6 -6
  165. package/dist/components/native-capabilities/notification-panel.d.ts +1 -1
  166. package/dist/components/native-capabilities/notification-panel.js +9 -9
  167. package/dist/components/native-capabilities/power-blocker-controller.d.ts +1 -1
  168. package/dist/components/native-capabilities/power-blocker-controller.js +1 -1
  169. package/dist/components/native-capabilities/power-panel.d.ts +1 -1
  170. package/dist/components/native-capabilities/power-panel.d.ts.map +1 -1
  171. package/dist/components/native-capabilities/power-panel.js +12 -12
  172. package/dist/components/native-capabilities/readout.d.ts.map +1 -1
  173. package/dist/components/native-capabilities/readout.js +2 -2
  174. package/dist/components/native-capabilities/screen-share-preview.js +6 -6
  175. package/dist/components/native-capabilities/secure-storage-panel.d.ts +1 -1
  176. package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -1
  177. package/dist/components/native-capabilities/secure-storage-panel.js +11 -11
  178. package/dist/components/native-capabilities/serial-console.d.ts +2 -2
  179. package/dist/components/native-capabilities/serial-console.d.ts.map +1 -1
  180. package/dist/components/native-capabilities/serial-console.js +11 -11
  181. package/dist/components/native-capabilities/shortcut-recorder.d.ts +1 -1
  182. package/dist/components/native-capabilities/shortcut-recorder.js +5 -5
  183. package/dist/components/native-capabilities/stream-log.js +3 -3
  184. package/dist/components/native-capabilities/system-audio-monitor.d.ts +1 -1
  185. package/dist/components/native-capabilities/system-audio-monitor.js +12 -12
  186. package/dist/components/native-capabilities/usb-panel.d.ts +5 -5
  187. package/dist/components/native-capabilities/usb-panel.js +15 -15
  188. package/dist/components/native-capabilities/use-capability.d.ts +1 -1
  189. package/dist/components/native-capabilities/use-capability.js +1 -1
  190. package/dist/components/rich-media-player.js +3 -3
  191. package/dist/components/ui/accordion.js +3 -3
  192. package/dist/components/ui/alert-dialog.d.ts +5 -3
  193. package/dist/components/ui/alert-dialog.d.ts.map +1 -1
  194. package/dist/components/ui/alert-dialog.js +20 -10
  195. package/dist/components/ui/alert.d.ts +2 -2
  196. package/dist/components/ui/alert.d.ts.map +1 -1
  197. package/dist/components/ui/alert.js +11 -11
  198. package/dist/components/ui/app-frame.d.ts +7 -1
  199. package/dist/components/ui/app-frame.d.ts.map +1 -1
  200. package/dist/components/ui/app-frame.js +52 -16
  201. package/dist/components/ui/avatar.js +5 -5
  202. package/dist/components/ui/badge.d.ts +1 -1
  203. package/dist/components/ui/badge.js +4 -4
  204. package/dist/components/ui/breadcrumb.js +2 -2
  205. package/dist/components/ui/button-group.d.ts +1 -1
  206. package/dist/components/ui/button-group.js +4 -4
  207. package/dist/components/ui/button.d.ts +6 -4
  208. package/dist/components/ui/button.d.ts.map +1 -1
  209. package/dist/components/ui/button.js +50 -18
  210. package/dist/components/ui/calendar.d.ts +1 -1
  211. package/dist/components/ui/calendar.d.ts.map +1 -1
  212. package/dist/components/ui/calendar.js +15 -15
  213. package/dist/components/ui/card.js +3 -3
  214. package/dist/components/ui/carousel.d.ts +1 -1
  215. package/dist/components/ui/carousel.js +4 -4
  216. package/dist/components/ui/chart.js +5 -5
  217. package/dist/components/ui/checkbox.d.ts.map +1 -1
  218. package/dist/components/ui/checkbox.js +2 -2
  219. package/dist/components/ui/collapsible.js +3 -3
  220. package/dist/components/ui/color-well.js +2 -2
  221. package/dist/components/ui/combobox.js +9 -9
  222. package/dist/components/ui/command.d.ts +1 -1
  223. package/dist/components/ui/command.d.ts.map +1 -1
  224. package/dist/components/ui/command.js +9 -9
  225. package/dist/components/ui/confirm-dialog.d.ts +1 -1
  226. package/dist/components/ui/confirm-dialog.d.ts.map +1 -1
  227. package/dist/components/ui/confirm-dialog.js +2 -2
  228. package/dist/components/ui/context-menu.d.ts +16 -5
  229. package/dist/components/ui/context-menu.d.ts.map +1 -1
  230. package/dist/components/ui/context-menu.js +92 -16
  231. package/dist/components/ui/date-field.d.ts.map +1 -1
  232. package/dist/components/ui/date-field.js +8 -8
  233. package/dist/components/ui/date-picker.d.ts +2 -2
  234. package/dist/components/ui/date-picker.js +7 -7
  235. package/dist/components/ui/dialog-primary-action.d.ts +4 -0
  236. package/dist/components/ui/dialog-primary-action.d.ts.map +1 -0
  237. package/dist/components/ui/dialog-primary-action.js +37 -0
  238. package/dist/components/ui/dialog.d.ts +6 -2
  239. package/dist/components/ui/dialog.d.ts.map +1 -1
  240. package/dist/components/ui/dialog.js +20 -7
  241. package/dist/components/ui/drawer.js +4 -4
  242. package/dist/components/ui/dropdown-menu.d.ts +15 -5
  243. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  244. package/dist/components/ui/dropdown-menu.js +98 -16
  245. package/dist/components/ui/edge-fade.js +1 -1
  246. package/dist/components/ui/empty.d.ts +1 -1
  247. package/dist/components/ui/empty.js +5 -5
  248. package/dist/components/ui/error-boundary-view.d.ts +12 -0
  249. package/dist/components/ui/error-boundary-view.d.ts.map +1 -0
  250. package/dist/components/ui/error-boundary-view.js +8 -0
  251. package/dist/components/ui/field.d.ts +1 -1
  252. package/dist/components/ui/field.d.ts.map +1 -1
  253. package/dist/components/ui/field.js +9 -9
  254. package/dist/components/ui/form.js +4 -4
  255. package/dist/components/ui/grid.d.ts.map +1 -1
  256. package/dist/components/ui/grid.js +5 -5
  257. package/dist/components/ui/hover-card.js +2 -2
  258. package/dist/components/ui/icon-button.d.ts +1 -1
  259. package/dist/components/ui/icon-button.d.ts.map +1 -1
  260. package/dist/components/ui/icon-button.js +3 -4
  261. package/dist/components/ui/index.d.ts +77 -76
  262. package/dist/components/ui/index.d.ts.map +1 -1
  263. package/dist/components/ui/index.js +77 -76
  264. package/dist/components/ui/input-group.d.ts +3 -3
  265. package/dist/components/ui/input-group.js +14 -14
  266. package/dist/components/ui/input-otp.js +3 -3
  267. package/dist/components/ui/input.js +2 -2
  268. package/dist/components/ui/inspector.d.ts +1 -1
  269. package/dist/components/ui/inspector.js +6 -6
  270. package/dist/components/ui/item.d.ts +1 -1
  271. package/dist/components/ui/item.js +7 -7
  272. package/dist/components/ui/kbd.js +2 -2
  273. package/dist/components/ui/label.js +2 -2
  274. package/dist/components/ui/list.d.ts.map +1 -1
  275. package/dist/components/ui/list.js +5 -5
  276. package/dist/components/ui/material.js +3 -3
  277. package/dist/components/ui/menu-items.d.ts +28 -0
  278. package/dist/components/ui/menu-items.d.ts.map +1 -0
  279. package/dist/components/ui/menu-items.js +111 -0
  280. package/dist/components/ui/menubar.js +11 -11
  281. package/dist/components/ui/message-scroller-controller.d.ts +1 -1
  282. package/dist/components/ui/message-scroller-controller.js +1 -1
  283. package/dist/components/ui/message-scroller-primitive.d.ts +1 -1
  284. package/dist/components/ui/message-scroller-primitive.js +1 -1
  285. package/dist/components/ui/message-scroller.d.ts +2 -2
  286. package/dist/components/ui/message-scroller.js +3 -3
  287. package/dist/components/ui/navigation-button-group.d.ts +2 -2
  288. package/dist/components/ui/navigation-button-group.js +2 -2
  289. package/dist/components/ui/navigation-menu.js +6 -6
  290. package/dist/components/ui/notification-dot.js +2 -2
  291. package/dist/components/ui/number-input.js +8 -8
  292. package/dist/components/ui/pagination.d.ts +1 -1
  293. package/dist/components/ui/pagination.js +2 -2
  294. package/dist/components/ui/panel.d.ts +1 -1
  295. package/dist/components/ui/panel.js +3 -3
  296. package/dist/components/ui/popover.d.ts +1 -1
  297. package/dist/components/ui/popover.js +3 -3
  298. package/dist/components/ui/progress.js +2 -2
  299. package/dist/components/ui/radio-group.d.ts.map +1 -1
  300. package/dist/components/ui/radio-group.js +2 -2
  301. package/dist/components/ui/resizable.d.ts +1 -1
  302. package/dist/components/ui/resizable.d.ts.map +1 -1
  303. package/dist/components/ui/resizable.js +15 -4
  304. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  305. package/dist/components/ui/scroll-area.js +3 -3
  306. package/dist/components/ui/search-field.js +7 -7
  307. package/dist/components/ui/segmented-control.js +9 -9
  308. package/dist/components/ui/select.d.ts.map +1 -1
  309. package/dist/components/ui/select.js +6 -6
  310. package/dist/components/ui/separator.js +1 -1
  311. package/dist/components/ui/sheet.js +4 -4
  312. package/dist/components/ui/sidebar.d.ts +5 -5
  313. package/dist/components/ui/sidebar.d.ts.map +1 -1
  314. package/dist/components/ui/sidebar.js +111 -24
  315. package/dist/components/ui/skeleton.js +2 -2
  316. package/dist/components/ui/slider.d.ts +3 -1
  317. package/dist/components/ui/slider.d.ts.map +1 -1
  318. package/dist/components/ui/slider.js +3 -3
  319. package/dist/components/ui/sonner.js +1 -1
  320. package/dist/components/ui/spinner.d.ts.map +1 -1
  321. package/dist/components/ui/spinner.js +2 -2
  322. package/dist/components/ui/split-view.js +1 -1
  323. package/dist/components/ui/status.d.ts +1 -1
  324. package/dist/components/ui/status.d.ts.map +1 -1
  325. package/dist/components/ui/status.js +10 -9
  326. package/dist/components/ui/switch.js +2 -2
  327. package/dist/components/ui/table.d.ts.map +1 -1
  328. package/dist/components/ui/table.js +7 -7
  329. package/dist/components/ui/tabs.js +3 -3
  330. package/dist/components/ui/text.d.ts +2 -2
  331. package/dist/components/ui/text.js +19 -19
  332. package/dist/components/ui/textarea.js +2 -2
  333. package/dist/components/ui/toggle-group.d.ts +1 -1
  334. package/dist/components/ui/toggle-group.js +4 -4
  335. package/dist/components/ui/toggle.d.ts +1 -1
  336. package/dist/components/ui/toggle.js +10 -10
  337. package/dist/components/ui/toolbar.d.ts +7 -7
  338. package/dist/components/ui/toolbar.js +7 -7
  339. package/dist/components/ui/tooltip.d.ts +2 -2
  340. package/dist/components/ui/tooltip.js +5 -5
  341. package/dist/index.d.ts +21 -15
  342. package/dist/index.d.ts.map +1 -1
  343. package/dist/index.js +22 -15
  344. package/dist/lib/frame-lifecycle.d.ts +49 -0
  345. package/dist/lib/frame-lifecycle.d.ts.map +1 -1
  346. package/dist/lib/frame-lifecycle.js +163 -1
  347. package/dist/lib/host-date-time-picker.d.ts +36 -0
  348. package/dist/lib/host-date-time-picker.d.ts.map +1 -0
  349. package/dist/lib/host-date-time-picker.js +162 -0
  350. package/dist/lib/host-file-dialog.d.ts +66 -0
  351. package/dist/lib/host-file-dialog.d.ts.map +1 -0
  352. package/dist/lib/host-file-dialog.js +221 -0
  353. package/dist/lib/host-native-menu.d.ts +116 -0
  354. package/dist/lib/host-native-menu.d.ts.map +1 -0
  355. package/dist/lib/host-native-menu.js +242 -0
  356. package/dist/lib/host-services.d.ts +13 -0
  357. package/dist/lib/host-services.d.ts.map +1 -0
  358. package/dist/lib/host-services.js +161 -0
  359. package/dist/lib/host-share.d.ts +39 -0
  360. package/dist/lib/host-share.d.ts.map +1 -0
  361. package/dist/lib/host-share.js +161 -0
  362. package/dist/lib/host-web-surface.d.ts +31 -0
  363. package/dist/lib/host-web-surface.d.ts.map +1 -0
  364. package/dist/lib/host-web-surface.js +116 -0
  365. package/dist/lib/native-capabilities/access.d.ts +2 -2
  366. package/dist/lib/native-capabilities/access.js +2 -2
  367. package/dist/lib/native-capabilities/bluetooth-access.d.ts +1 -1
  368. package/dist/lib/native-capabilities/bluetooth-access.js +2 -2
  369. package/dist/lib/native-capabilities/bluetooth-connection.d.ts +1 -1
  370. package/dist/lib/native-capabilities/bluetooth-connection.js +1 -1
  371. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +1 -1
  372. package/dist/lib/native-capabilities/bluetooth-gatt.js +1 -1
  373. package/dist/lib/native-capabilities/bluetooth-internal.d.ts +2 -2
  374. package/dist/lib/native-capabilities/bluetooth-internal.js +1 -1
  375. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +2 -2
  376. package/dist/lib/native-capabilities/bluetooth-native-fallback.js +2 -2
  377. package/dist/lib/native-capabilities/bluetooth.d.ts +6 -6
  378. package/dist/lib/native-capabilities/bluetooth.js +4 -4
  379. package/dist/lib/native-capabilities/bridge.d.ts +1 -1
  380. package/dist/lib/native-capabilities/bridge.js +2 -2
  381. package/dist/lib/native-capabilities/capabilities.d.ts +1 -1
  382. package/dist/lib/native-capabilities/capabilities.js +1 -1
  383. package/dist/lib/native-capabilities/clipboard.js +2 -2
  384. package/dist/lib/native-capabilities/device-io-errors.d.ts +1 -1
  385. package/dist/lib/native-capabilities/device-io-errors.js +1 -1
  386. package/dist/lib/native-capabilities/displays.d.ts +1 -1
  387. package/dist/lib/native-capabilities/displays.js +1 -1
  388. package/dist/lib/native-capabilities/global-shortcuts.d.ts +2 -2
  389. package/dist/lib/native-capabilities/global-shortcuts.js +1 -1
  390. package/dist/lib/native-capabilities/haptics.d.ts +1 -1
  391. package/dist/lib/native-capabilities/haptics.js +1 -1
  392. package/dist/lib/native-capabilities/hid-native.d.ts +2 -2
  393. package/dist/lib/native-capabilities/hid-native.js +3 -3
  394. package/dist/lib/native-capabilities/hid.js +5 -5
  395. package/dist/lib/native-capabilities/index.d.ts +39 -39
  396. package/dist/lib/native-capabilities/index.js +21 -21
  397. package/dist/lib/native-capabilities/local-authentication.d.ts +1 -1
  398. package/dist/lib/native-capabilities/local-authentication.js +1 -1
  399. package/dist/lib/native-capabilities/location.js +1 -1
  400. package/dist/lib/native-capabilities/media-permissions.d.ts +1 -1
  401. package/dist/lib/native-capabilities/media-permissions.js +1 -1
  402. package/dist/lib/native-capabilities/media.d.ts +1 -1
  403. package/dist/lib/native-capabilities/media.js +2 -2
  404. package/dist/lib/native-capabilities/midi-access.d.ts +1 -1
  405. package/dist/lib/native-capabilities/midi-access.js +3 -3
  406. package/dist/lib/native-capabilities/midi-internal.d.ts +1 -1
  407. package/dist/lib/native-capabilities/midi-internal.js +1 -1
  408. package/dist/lib/native-capabilities/midi-native-fallback.d.ts +1 -1
  409. package/dist/lib/native-capabilities/midi-native-fallback.js +2 -2
  410. package/dist/lib/native-capabilities/midi-ports.d.ts +1 -1
  411. package/dist/lib/native-capabilities/midi-ports.js +1 -1
  412. package/dist/lib/native-capabilities/midi.d.ts +5 -5
  413. package/dist/lib/native-capabilities/midi.js +3 -3
  414. package/dist/lib/native-capabilities/native-device-io.d.ts +1 -1
  415. package/dist/lib/native-capabilities/native-device-io.js +1 -1
  416. package/dist/lib/native-capabilities/native-device-lifecycle.js +1 -1
  417. package/dist/lib/native-capabilities/notifications.d.ts +2 -2
  418. package/dist/lib/native-capabilities/notifications.js +1 -1
  419. package/dist/lib/native-capabilities/power-session.d.ts +2 -2
  420. package/dist/lib/native-capabilities/power-session.js +1 -1
  421. package/dist/lib/native-capabilities/secure-storage.d.ts +1 -1
  422. package/dist/lib/native-capabilities/secure-storage.js +1 -1
  423. package/dist/lib/native-capabilities/serial-native.d.ts +2 -2
  424. package/dist/lib/native-capabilities/serial-native.js +3 -3
  425. package/dist/lib/native-capabilities/serial.js +5 -5
  426. package/dist/lib/native-capabilities/system-audio.d.ts +1 -1
  427. package/dist/lib/native-capabilities/system-audio.js +1 -1
  428. package/dist/lib/native-capabilities/usb-native.d.ts +2 -2
  429. package/dist/lib/native-capabilities/usb-native.js +3 -3
  430. package/dist/lib/native-capabilities/usb.js +5 -5
  431. package/dist/lib/native-hardware/bluetooth-access.d.ts +1 -1
  432. package/dist/lib/native-hardware/bluetooth-access.js +1 -1
  433. package/dist/lib/native-hardware/bluetooth-connection.d.ts +1 -1
  434. package/dist/lib/native-hardware/bluetooth-connection.js +1 -1
  435. package/dist/lib/native-hardware/bluetooth-gatt.d.ts +1 -1
  436. package/dist/lib/native-hardware/bluetooth-gatt.js +1 -1
  437. package/dist/lib/native-hardware/bluetooth-internal.d.ts +2 -2
  438. package/dist/lib/native-hardware/bluetooth-internal.js +1 -1
  439. package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts +2 -2
  440. package/dist/lib/native-hardware/bluetooth-native-fallback.js +2 -2
  441. package/dist/lib/native-hardware/bluetooth.d.ts +6 -6
  442. package/dist/lib/native-hardware/bluetooth.js +4 -4
  443. package/dist/lib/native-hardware/bridge.d.ts +1 -1
  444. package/dist/lib/native-hardware/bridge.js +2 -2
  445. package/dist/lib/native-hardware/capabilities.d.ts +1 -1
  446. package/dist/lib/native-hardware/capabilities.js +1 -1
  447. package/dist/lib/native-hardware/clipboard.js +1 -1
  448. package/dist/lib/native-hardware/device-io-errors.d.ts +1 -1
  449. package/dist/lib/native-hardware/device-io-errors.js +1 -1
  450. package/dist/lib/native-hardware/displays.d.ts +1 -1
  451. package/dist/lib/native-hardware/displays.js +1 -1
  452. package/dist/lib/native-hardware/global-shortcuts.d.ts +2 -2
  453. package/dist/lib/native-hardware/global-shortcuts.js +1 -1
  454. package/dist/lib/native-hardware/haptics.d.ts +1 -1
  455. package/dist/lib/native-hardware/haptics.js +1 -1
  456. package/dist/lib/native-hardware/hid-native.d.ts +2 -2
  457. package/dist/lib/native-hardware/hid-native.js +3 -3
  458. package/dist/lib/native-hardware/hid.js +4 -4
  459. package/dist/lib/native-hardware/index.d.ts +37 -37
  460. package/dist/lib/native-hardware/index.js +20 -20
  461. package/dist/lib/native-hardware/local-authentication.d.ts +1 -1
  462. package/dist/lib/native-hardware/local-authentication.js +1 -1
  463. package/dist/lib/native-hardware/location.js +1 -1
  464. package/dist/lib/native-hardware/media-permissions.d.ts +1 -1
  465. package/dist/lib/native-hardware/media-permissions.js +1 -1
  466. package/dist/lib/native-hardware/media.d.ts +1 -1
  467. package/dist/lib/native-hardware/media.js +1 -1
  468. package/dist/lib/native-hardware/midi-access.d.ts +1 -1
  469. package/dist/lib/native-hardware/midi-access.js +2 -2
  470. package/dist/lib/native-hardware/midi-internal.d.ts +1 -1
  471. package/dist/lib/native-hardware/midi-internal.js +1 -1
  472. package/dist/lib/native-hardware/midi-native-fallback.d.ts +1 -1
  473. package/dist/lib/native-hardware/midi-native-fallback.js +2 -2
  474. package/dist/lib/native-hardware/midi-ports.d.ts +1 -1
  475. package/dist/lib/native-hardware/midi-ports.js +1 -1
  476. package/dist/lib/native-hardware/midi.d.ts +5 -5
  477. package/dist/lib/native-hardware/midi.js +3 -3
  478. package/dist/lib/native-hardware/native-device-io.d.ts +1 -1
  479. package/dist/lib/native-hardware/native-device-io.js +1 -1
  480. package/dist/lib/native-hardware/native-device-lifecycle.js +1 -1
  481. package/dist/lib/native-hardware/notifications.d.ts +2 -2
  482. package/dist/lib/native-hardware/notifications.js +1 -1
  483. package/dist/lib/native-hardware/power-session.d.ts +2 -2
  484. package/dist/lib/native-hardware/power-session.js +1 -1
  485. package/dist/lib/native-hardware/secure-storage.d.ts +1 -1
  486. package/dist/lib/native-hardware/secure-storage.js +1 -1
  487. package/dist/lib/native-hardware/serial-native.d.ts +2 -2
  488. package/dist/lib/native-hardware/serial-native.js +3 -3
  489. package/dist/lib/native-hardware/serial.js +4 -4
  490. package/dist/lib/native-hardware/system-audio.d.ts +1 -1
  491. package/dist/lib/native-hardware/system-audio.js +1 -1
  492. package/dist/lib/native-hardware/usb-native.d.ts +2 -2
  493. package/dist/lib/native-hardware/usb-native.js +3 -3
  494. package/dist/lib/native-hardware/usb.js +4 -4
  495. package/dist/lib/theme.js +1 -1
  496. package/docs/README.md +1 -0
  497. package/docs/design-tokens.md +28 -6
  498. package/docs/foundations.md +4 -2
  499. package/docs/visual-regression.md +78 -0
  500. package/package.json +15 -4
  501. package/src/components/ui/alert-dialog.md +27 -0
  502. package/src/components/ui/button.md +10 -3
  503. package/src/components/ui/confirm-dialog.md +97 -0
  504. package/src/components/ui/context-menu.md +158 -0
  505. package/src/components/ui/dialog.md +23 -4
  506. package/src/components/ui/dropdown-menu.md +165 -0
  507. package/src/components/ui/error-boundary-view.md +98 -0
  508. package/src/components/ui/hover-card.md +90 -0
  509. package/src/components/ui/select.md +111 -0
  510. package/src/lib/host-date-time-picker.md +29 -0
  511. package/src/lib/host-file-dialog.md +76 -0
  512. package/src/lib/host-native-menu.md +67 -0
  513. package/src/lib/host-share.md +36 -0
  514. package/src/lib/host-web-surface.md +66 -0
  515. package/src/styles/index.css +141 -68
@@ -0,0 +1,221 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { HostServiceRequestError, isHostServiceAvailable, requestHostService, } from './host-services.js';
3
+ const HOST_CONTEXT_CHANGE_EVENT = 'moldable:host-context-change';
4
+ const FILE_DIALOG_SERVICE_NAME = 'fileDialog';
5
+ const MAX_TEXT_LENGTH = 512;
6
+ const MAX_DEFAULT_NAME_LENGTH = 255;
7
+ const MAX_FILTERS = 32;
8
+ const MAX_FILTER_NAME_LENGTH = 128;
9
+ const MAX_EXTENSIONS_PER_FILTER = 64;
10
+ const MAX_EXTENSION_LENGTH = 64;
11
+ function isRecord(value) {
12
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
13
+ }
14
+ function assertOnlyKeys(value, allowed, label) {
15
+ if (!Object.keys(value).every((key) => allowed.has(key))) {
16
+ throw new TypeError(`${label} contain an unknown property.`);
17
+ }
18
+ }
19
+ function validateOptionalText(label, value) {
20
+ if (value !== undefined &&
21
+ (typeof value !== 'string' ||
22
+ value.trim().length === 0 ||
23
+ value.length > MAX_TEXT_LENGTH ||
24
+ value.includes('\0'))) {
25
+ throw new TypeError(`${label} must contain 1–${MAX_TEXT_LENGTH} characters.`);
26
+ }
27
+ }
28
+ function validateDefaultLocation(value) {
29
+ if (value !== undefined &&
30
+ value !== 'documents' &&
31
+ value !== 'downloads' &&
32
+ value !== 'desktop' &&
33
+ value !== 'home' &&
34
+ value !== 'appData') {
35
+ throw new TypeError('File-dialog defaultLocation is not supported.');
36
+ }
37
+ }
38
+ function validateFilters(filters) {
39
+ if (filters === undefined)
40
+ return;
41
+ if (!Array.isArray(filters) || filters.length > MAX_FILTERS) {
42
+ throw new TypeError(`File dialogs support at most ${MAX_FILTERS} filters.`);
43
+ }
44
+ for (const filter of filters) {
45
+ if (!isRecord(filter)) {
46
+ throw new TypeError('File-dialog filters must be objects.');
47
+ }
48
+ assertOnlyKeys(filter, new Set(['name', 'extensions']), 'File-dialog filters');
49
+ if (typeof filter.name !== 'string' ||
50
+ filter.name.trim().length === 0 ||
51
+ filter.name.length > MAX_FILTER_NAME_LENGTH ||
52
+ filter.name.includes('\0') ||
53
+ !Array.isArray(filter.extensions) ||
54
+ filter.extensions.length === 0 ||
55
+ filter.extensions.length > MAX_EXTENSIONS_PER_FILTER) {
56
+ throw new TypeError('Each file-dialog filter requires a bounded name and extension list.');
57
+ }
58
+ if (!filter.extensions.every((extension) => typeof extension === 'string' &&
59
+ extension.length > 0 &&
60
+ extension.length <= MAX_EXTENSION_LENGTH &&
61
+ !extension.startsWith('.') &&
62
+ !/[\s/\\:*\0]/u.test(extension))) {
63
+ throw new TypeError('File-dialog extensions must omit dots, wildcards, whitespace, and path separators.');
64
+ }
65
+ }
66
+ }
67
+ const COMMON_KEYS = [
68
+ 'title',
69
+ 'buttonLabel',
70
+ 'filters',
71
+ 'defaultLocation',
72
+ 'signal',
73
+ 'timeoutMs',
74
+ ];
75
+ const OPEN_KEYS = new Set([...COMMON_KEYS, 'properties']);
76
+ const SAVE_KEYS = new Set([...COMMON_KEYS, 'defaultName', 'createDirectories']);
77
+ const OPEN_PROPERTY_KEYS = new Set([
78
+ 'multiple',
79
+ 'directories',
80
+ 'createDirectories',
81
+ 'showHidden',
82
+ ]);
83
+ function validateCommonOptions(options, keys) {
84
+ assertOnlyKeys(options, keys, 'File-dialog options');
85
+ validateOptionalText('File-dialog title', options.title);
86
+ validateOptionalText('File-dialog buttonLabel', options.buttonLabel);
87
+ validateDefaultLocation(options.defaultLocation);
88
+ validateFilters(options.filters);
89
+ }
90
+ function validateOpenOptions(options) {
91
+ if (!isRecord(options)) {
92
+ throw new TypeError('Open file-dialog options must be an object.');
93
+ }
94
+ validateCommonOptions(options, OPEN_KEYS);
95
+ if (options.properties === undefined)
96
+ return;
97
+ if (!isRecord(options.properties)) {
98
+ throw new TypeError('Open file-dialog properties must be an object.');
99
+ }
100
+ assertOnlyKeys(options.properties, OPEN_PROPERTY_KEYS, 'Open file-dialog properties');
101
+ if (!Object.values(options.properties).every((value) => typeof value === 'boolean')) {
102
+ throw new TypeError('Open file-dialog properties must be booleans.');
103
+ }
104
+ }
105
+ function validateSaveOptions(options) {
106
+ if (!isRecord(options)) {
107
+ throw new TypeError('Save file-dialog options must be an object.');
108
+ }
109
+ validateCommonOptions(options, SAVE_KEYS);
110
+ if (options.defaultName !== undefined &&
111
+ (typeof options.defaultName !== 'string' ||
112
+ options.defaultName.trim().length === 0 ||
113
+ options.defaultName.length > MAX_DEFAULT_NAME_LENGTH ||
114
+ /[/\\\0]/u.test(options.defaultName))) {
115
+ throw new TypeError(`Save-dialog defaultName must be a filename of 1–${MAX_DEFAULT_NAME_LENGTH} characters.`);
116
+ }
117
+ if (options.createDirectories !== undefined &&
118
+ typeof options.createDirectories !== 'boolean') {
119
+ throw new TypeError('Save-dialog createDirectories must be a boolean.');
120
+ }
121
+ }
122
+ function requestOptions(options) {
123
+ return {
124
+ signal: options.signal,
125
+ timeoutMs: options.timeoutMs,
126
+ };
127
+ }
128
+ function abortError() {
129
+ return new DOMException('The file-dialog request was aborted.', 'AbortError');
130
+ }
131
+ function isPath(value) {
132
+ return typeof value === 'string' && value.length > 0;
133
+ }
134
+ export async function openFileDialogWithHost(options = {}) {
135
+ validateOpenOptions(options);
136
+ if (options.signal?.aborted)
137
+ throw abortError();
138
+ if (!isHostServiceAvailable(FILE_DIALOG_SERVICE_NAME)) {
139
+ return { status: 'fallback' };
140
+ }
141
+ try {
142
+ const result = await requestHostService(FILE_DIALOG_SERVICE_NAME, {
143
+ mode: 'open',
144
+ ...(options.title === undefined ? {} : { title: options.title }),
145
+ ...(options.buttonLabel === undefined
146
+ ? {}
147
+ : { buttonLabel: options.buttonLabel }),
148
+ ...(options.filters === undefined ? {} : { filters: options.filters }),
149
+ ...(options.defaultLocation === undefined
150
+ ? {}
151
+ : { defaultLocation: options.defaultLocation }),
152
+ ...(options.properties === undefined
153
+ ? {}
154
+ : { properties: options.properties }),
155
+ }, requestOptions(options));
156
+ if (!isRecord(result) ||
157
+ !Array.isArray(result.paths) ||
158
+ result.paths.length === 0 ||
159
+ !result.paths.every(isPath)) {
160
+ throw new Error('The native open dialog returned an invalid result.');
161
+ }
162
+ return { status: 'completed', paths: result.paths };
163
+ }
164
+ catch (error) {
165
+ if (error instanceof HostServiceRequestError &&
166
+ error.status === 'cancelled') {
167
+ return { status: 'cancelled' };
168
+ }
169
+ throw error;
170
+ }
171
+ }
172
+ export async function saveFileDialogWithHost(options = {}) {
173
+ validateSaveOptions(options);
174
+ if (options.signal?.aborted)
175
+ throw abortError();
176
+ if (!isHostServiceAvailable(FILE_DIALOG_SERVICE_NAME)) {
177
+ return { status: 'fallback' };
178
+ }
179
+ try {
180
+ const result = await requestHostService(FILE_DIALOG_SERVICE_NAME, {
181
+ mode: 'save',
182
+ ...(options.title === undefined ? {} : { title: options.title }),
183
+ ...(options.buttonLabel === undefined
184
+ ? {}
185
+ : { buttonLabel: options.buttonLabel }),
186
+ ...(options.filters === undefined ? {} : { filters: options.filters }),
187
+ ...(options.defaultLocation === undefined
188
+ ? {}
189
+ : { defaultLocation: options.defaultLocation }),
190
+ ...(options.defaultName === undefined
191
+ ? {}
192
+ : { defaultName: options.defaultName }),
193
+ ...(options.createDirectories === undefined
194
+ ? {}
195
+ : { createDirectories: options.createDirectories }),
196
+ }, requestOptions(options));
197
+ if (!isRecord(result) || !isPath(result.path)) {
198
+ throw new Error('The native save dialog returned an invalid result.');
199
+ }
200
+ return { status: 'completed', path: result.path };
201
+ }
202
+ catch (error) {
203
+ if (error instanceof HostServiceRequestError &&
204
+ error.status === 'cancelled') {
205
+ return { status: 'cancelled' };
206
+ }
207
+ throw error;
208
+ }
209
+ }
210
+ export function useHostFileDialog() {
211
+ const [available, setAvailable] = useState(() => isHostServiceAvailable(FILE_DIALOG_SERVICE_NAME));
212
+ useEffect(() => {
213
+ const update = () => setAvailable(isHostServiceAvailable(FILE_DIALOG_SERVICE_NAME));
214
+ update();
215
+ window.addEventListener(HOST_CONTEXT_CHANGE_EVENT, update);
216
+ return () => window.removeEventListener(HOST_CONTEXT_CHANGE_EVENT, update);
217
+ }, []);
218
+ const open = useCallback((options) => openFileDialogWithHost(options), []);
219
+ const save = useCallback((options) => saveFileDialogWithHost(options), []);
220
+ return { available, open, save };
221
+ }
@@ -0,0 +1,116 @@
1
+ import type { LucideIcon } from 'lucide-react';
2
+ import { type HostServiceRequestOptions } from './host-services.js';
3
+ export declare const HOST_NATIVE_MENU_MAX_DEPTH = 3;
4
+ export declare const HOST_NATIVE_MENU_MAX_ITEMS = 200;
5
+ export declare const HOST_NATIVE_MENU_MAX_TITLE_LENGTH = 256;
6
+ export declare const HOST_NATIVE_MENU_MAX_SUBLABEL_LENGTH = 512;
7
+ export type NativeMenuItemKind = 'normal' | 'separator' | 'checkbox' | 'radio';
8
+ export interface NativeMenuShortcut {
9
+ key: string;
10
+ modifiers?: Array<'cmd' | 'shift' | 'alt' | 'ctrl'>;
11
+ }
12
+ interface MenuItemState {
13
+ enabled?: boolean;
14
+ shortcut?: NativeMenuShortcut;
15
+ destructive?: boolean;
16
+ }
17
+ interface NativeMenuItemBase extends MenuItemState {
18
+ sublabel?: string;
19
+ }
20
+ export type NativeMenuItem = (NativeMenuItemBase & {
21
+ id: string;
22
+ kind?: 'normal';
23
+ title: string;
24
+ checked?: never;
25
+ submenu?: NativeMenuItem[];
26
+ }) | (NativeMenuItemBase & {
27
+ id?: string;
28
+ kind: 'separator';
29
+ title?: string;
30
+ checked?: never;
31
+ submenu?: never;
32
+ }) | (NativeMenuItemBase & {
33
+ id: string;
34
+ kind: 'checkbox';
35
+ title: string;
36
+ checked?: boolean | 'mixed';
37
+ submenu?: never;
38
+ }) | (NativeMenuItemBase & {
39
+ id: string;
40
+ kind: 'radio';
41
+ title: string;
42
+ checked?: boolean;
43
+ submenu?: never;
44
+ });
45
+ interface RendererMenuItemBase extends MenuItemState {
46
+ id: string;
47
+ label: string;
48
+ /** Rendered only by the portable menu. */
49
+ icon?: LucideIcon;
50
+ /** Reserved for a future native-symbol allowlist. */
51
+ sfSymbol?: string;
52
+ }
53
+ /**
54
+ * A renderer-facing declarative menu item shared by portable and native menu
55
+ * paths. Despite the pluralized public name, roots accept `MenuItems[]`.
56
+ */
57
+ export type MenuItems = (RendererMenuItemBase & {
58
+ kind?: 'normal';
59
+ checked?: never;
60
+ submenu?: MenuItems[];
61
+ }) | {
62
+ id: string;
63
+ kind: 'separator';
64
+ label?: never;
65
+ icon?: never;
66
+ sfSymbol?: never;
67
+ enabled?: never;
68
+ checked?: never;
69
+ shortcut?: never;
70
+ destructive?: never;
71
+ submenu?: never;
72
+ } | (RendererMenuItemBase & {
73
+ kind: 'checkbox';
74
+ checked?: boolean | 'mixed';
75
+ submenu?: never;
76
+ }) | (RendererMenuItemBase & {
77
+ kind: 'radio';
78
+ checked?: boolean;
79
+ submenu?: never;
80
+ });
81
+ export interface HostNativeMenuAnchorRect {
82
+ x: number;
83
+ y: number;
84
+ width: number;
85
+ height: number;
86
+ }
87
+ export interface HostNativeMenuPoint {
88
+ x: number;
89
+ y: number;
90
+ }
91
+ export interface HostNativeMenuOptions extends HostServiceRequestOptions {
92
+ anchor?: Element | HostNativeMenuAnchorRect;
93
+ position?: HostNativeMenuPoint;
94
+ }
95
+ export type HostNativeMenuResult = {
96
+ status: 'completed';
97
+ selectedId: string;
98
+ } | {
99
+ status: 'cancelled';
100
+ } | {
101
+ status: 'fallback';
102
+ };
103
+ export interface HostNativeMenu {
104
+ available: boolean;
105
+ open: (items: NativeMenuItem[], options: HostNativeMenuOptions) => Promise<HostNativeMenuResult>;
106
+ }
107
+ /**
108
+ * Converts renderer menu items to the host wire model by explicit allowlist.
109
+ * Portable-only icons and sfSymbol metadata, plus any unexpected runtime
110
+ * fields, are intentionally omitted.
111
+ */
112
+ export declare function toNativeMenuItems(items: MenuItems[]): NativeMenuItem[];
113
+ export declare function openNativeMenuWithHost(items: NativeMenuItem[], options: HostNativeMenuOptions): Promise<HostNativeMenuResult>;
114
+ export declare function useHostNativeMenu(): HostNativeMenu;
115
+ export {};
116
+ //# sourceMappingURL=host-native-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-native-menu.d.ts","sourceRoot":"","sources":["../../src/lib/host-native-menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,242 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { HostServiceRequestError, isHostServiceAvailable, requestHostService, } from './host-services.js';
3
+ const HOST_CONTEXT_CHANGE_EVENT = 'moldable:host-context-change';
4
+ const NATIVE_MENU_SERVICE_NAME = 'nativeMenu';
5
+ export const HOST_NATIVE_MENU_MAX_DEPTH = 3;
6
+ export const HOST_NATIVE_MENU_MAX_ITEMS = 200;
7
+ export const HOST_NATIVE_MENU_MAX_TITLE_LENGTH = 256;
8
+ export const HOST_NATIVE_MENU_MAX_SUBLABEL_LENGTH = 512;
9
+ function nativeMenuItemState(item) {
10
+ return {
11
+ ...(item.enabled !== undefined ? { enabled: item.enabled } : {}),
12
+ ...(item.shortcut
13
+ ? {
14
+ shortcut: {
15
+ key: item.shortcut.key,
16
+ ...(item.shortcut.modifiers
17
+ ? { modifiers: [...item.shortcut.modifiers] }
18
+ : {}),
19
+ },
20
+ }
21
+ : {}),
22
+ ...(item.destructive !== undefined
23
+ ? { destructive: item.destructive }
24
+ : {}),
25
+ };
26
+ }
27
+ /**
28
+ * Converts renderer menu items to the host wire model by explicit allowlist.
29
+ * Portable-only icons and sfSymbol metadata, plus any unexpected runtime
30
+ * fields, are intentionally omitted.
31
+ */
32
+ export function toNativeMenuItems(items) {
33
+ return items.map((item) => {
34
+ if (item.kind === 'separator') {
35
+ return { id: item.id, kind: 'separator' };
36
+ }
37
+ const state = nativeMenuItemState(item);
38
+ if (item.kind === 'checkbox') {
39
+ return {
40
+ id: item.id,
41
+ kind: 'checkbox',
42
+ title: item.label,
43
+ ...state,
44
+ ...(item.checked !== undefined ? { checked: item.checked } : {}),
45
+ };
46
+ }
47
+ if (item.kind === 'radio') {
48
+ return {
49
+ id: item.id,
50
+ kind: 'radio',
51
+ title: item.label,
52
+ ...state,
53
+ ...(item.checked !== undefined ? { checked: item.checked } : {}),
54
+ };
55
+ }
56
+ return {
57
+ id: item.id,
58
+ title: item.label,
59
+ ...state,
60
+ ...(item.submenu ? { submenu: toNativeMenuItems(item.submenu) } : {}),
61
+ };
62
+ });
63
+ }
64
+ function finitePoint(value) {
65
+ return Number.isFinite(value.x) && Number.isFinite(value.y);
66
+ }
67
+ function menuAnchorRect(anchor) {
68
+ const rect = typeof Element !== 'undefined' && anchor instanceof Element
69
+ ? anchor.getBoundingClientRect()
70
+ : anchor;
71
+ if (!finitePoint(rect) ||
72
+ !Number.isFinite(rect.width) ||
73
+ !Number.isFinite(rect.height) ||
74
+ rect.width < 0 ||
75
+ rect.height < 0) {
76
+ throw new TypeError('Native menu anchors require a finite, non-negative rect.');
77
+ }
78
+ return {
79
+ x: rect.x,
80
+ y: rect.y,
81
+ width: rect.width,
82
+ height: rect.height,
83
+ };
84
+ }
85
+ function validateShortcut(shortcut) {
86
+ if (typeof shortcut.key !== 'string' || shortcut.key.length === 0) {
87
+ throw new TypeError('Native menu shortcuts require a non-empty key.');
88
+ }
89
+ if (shortcut.modifiers !== undefined &&
90
+ (!Array.isArray(shortcut.modifiers) ||
91
+ !shortcut.modifiers.every((modifier) => modifier === 'cmd' ||
92
+ modifier === 'shift' ||
93
+ modifier === 'alt' ||
94
+ modifier === 'ctrl'))) {
95
+ throw new TypeError('Native menu shortcuts contain an invalid modifier.');
96
+ }
97
+ }
98
+ function validateMenuItems(items) {
99
+ if (!Array.isArray(items) ||
100
+ items.length === 0 ||
101
+ items.length > HOST_NATIVE_MENU_MAX_ITEMS) {
102
+ throw new TypeError(`Native menus require 1–${HOST_NATIVE_MENU_MAX_ITEMS} total items.`);
103
+ }
104
+ const ids = new Set();
105
+ let totalItems = 0;
106
+ const visit = (values, depth) => {
107
+ if (depth > HOST_NATIVE_MENU_MAX_DEPTH) {
108
+ throw new TypeError(`Native menu depth must not exceed ${HOST_NATIVE_MENU_MAX_DEPTH}.`);
109
+ }
110
+ for (const item of values) {
111
+ totalItems += 1;
112
+ if (totalItems > HOST_NATIVE_MENU_MAX_ITEMS) {
113
+ throw new TypeError(`Native menus must not exceed ${HOST_NATIVE_MENU_MAX_ITEMS} total items.`);
114
+ }
115
+ if (!item || typeof item !== 'object' || Array.isArray(item)) {
116
+ throw new TypeError('Native menu items must be objects.');
117
+ }
118
+ const kind = item.kind ?? 'normal';
119
+ if (kind !== 'normal' &&
120
+ kind !== 'separator' &&
121
+ kind !== 'checkbox' &&
122
+ kind !== 'radio') {
123
+ throw new TypeError('Native menu items contain an unsupported kind.');
124
+ }
125
+ if (kind !== 'separator') {
126
+ if (typeof item.id !== 'string' ||
127
+ item.id.trim().length === 0 ||
128
+ ids.has(item.id)) {
129
+ throw new TypeError('Selectable native menu items require unique, non-empty ids.');
130
+ }
131
+ ids.add(item.id);
132
+ if (typeof item.title !== 'string' ||
133
+ item.title.length === 0 ||
134
+ item.title.length > HOST_NATIVE_MENU_MAX_TITLE_LENGTH) {
135
+ throw new TypeError(`Native menu item titles must contain 1–${HOST_NATIVE_MENU_MAX_TITLE_LENGTH} characters.`);
136
+ }
137
+ }
138
+ else {
139
+ if (item.id !== undefined && typeof item.id !== 'string') {
140
+ throw new TypeError('Native menu separator ids must be strings when provided.');
141
+ }
142
+ if (item.title !== undefined &&
143
+ (typeof item.title !== 'string' ||
144
+ item.title.length > HOST_NATIVE_MENU_MAX_TITLE_LENGTH)) {
145
+ throw new TypeError(`Native menu separator titles must not exceed ${HOST_NATIVE_MENU_MAX_TITLE_LENGTH} characters.`);
146
+ }
147
+ }
148
+ if (item.sublabel !== undefined &&
149
+ (typeof item.sublabel !== 'string' ||
150
+ item.sublabel.length > HOST_NATIVE_MENU_MAX_SUBLABEL_LENGTH)) {
151
+ throw new TypeError(`Native menu sublabels must not exceed ${HOST_NATIVE_MENU_MAX_SUBLABEL_LENGTH} characters.`);
152
+ }
153
+ if (item.enabled !== undefined && typeof item.enabled !== 'boolean') {
154
+ throw new TypeError('Native menu enabled values must be booleans.');
155
+ }
156
+ if (item.destructive !== undefined &&
157
+ typeof item.destructive !== 'boolean') {
158
+ throw new TypeError('Native menu destructive values must be booleans.');
159
+ }
160
+ if (item.shortcut !== undefined)
161
+ validateShortcut(item.shortcut);
162
+ if (kind === 'checkbox' || kind === 'radio') {
163
+ if (item.checked !== undefined &&
164
+ item.checked !== true &&
165
+ item.checked !== false &&
166
+ item.checked !== 'mixed') {
167
+ throw new TypeError('Native menu checked values must be true, false, or mixed.');
168
+ }
169
+ if (kind === 'radio' && item.checked === 'mixed') {
170
+ throw new TypeError('Native menu radio items do not support the mixed state.');
171
+ }
172
+ }
173
+ else if (item.checked !== undefined) {
174
+ throw new TypeError('Only checkbox and radio native menu items may be checked.');
175
+ }
176
+ if (item.submenu !== undefined) {
177
+ if (kind !== 'normal' || !Array.isArray(item.submenu)) {
178
+ throw new TypeError('Only normal native menu items may contain submenu arrays.');
179
+ }
180
+ visit(item.submenu, depth + 1);
181
+ }
182
+ }
183
+ };
184
+ visit(items, 1);
185
+ }
186
+ function validatePlacement(options) {
187
+ const hasAnchor = options.anchor !== undefined;
188
+ const hasPosition = options.position !== undefined;
189
+ if (hasAnchor === hasPosition) {
190
+ throw new TypeError('Native menus require exactly one anchor or pointer position.');
191
+ }
192
+ if (options.anchor)
193
+ return { anchor: menuAnchorRect(options.anchor) };
194
+ if (!options.position || !finitePoint(options.position)) {
195
+ throw new TypeError('Native menu positions require finite x and y coordinates.');
196
+ }
197
+ return { position: { ...options.position } };
198
+ }
199
+ function abortError() {
200
+ return new DOMException('The native menu request was aborted.', 'AbortError');
201
+ }
202
+ export async function openNativeMenuWithHost(items, options) {
203
+ validateMenuItems(items);
204
+ const placement = validatePlacement(options);
205
+ if (options.signal?.aborted)
206
+ throw abortError();
207
+ if (!isHostServiceAvailable(NATIVE_MENU_SERVICE_NAME)) {
208
+ return { status: 'fallback' };
209
+ }
210
+ try {
211
+ const result = await requestHostService(NATIVE_MENU_SERVICE_NAME, { items, ...placement }, {
212
+ signal: options.signal,
213
+ timeoutMs: options.timeoutMs,
214
+ });
215
+ if (typeof result !== 'object' ||
216
+ result === null ||
217
+ !('selectedId' in result) ||
218
+ typeof result.selectedId !== 'string' ||
219
+ result.selectedId.length === 0) {
220
+ throw new Error('The native menu returned an invalid result.');
221
+ }
222
+ return { status: 'completed', selectedId: result.selectedId };
223
+ }
224
+ catch (error) {
225
+ if (error instanceof HostServiceRequestError &&
226
+ error.status === 'cancelled') {
227
+ return { status: 'cancelled' };
228
+ }
229
+ throw error;
230
+ }
231
+ }
232
+ export function useHostNativeMenu() {
233
+ const [available, setAvailable] = useState(() => isHostServiceAvailable(NATIVE_MENU_SERVICE_NAME));
234
+ useEffect(() => {
235
+ const update = () => setAvailable(isHostServiceAvailable(NATIVE_MENU_SERVICE_NAME));
236
+ update();
237
+ window.addEventListener(HOST_CONTEXT_CHANGE_EVENT, update);
238
+ return () => window.removeEventListener(HOST_CONTEXT_CHANGE_EVENT, update);
239
+ }, []);
240
+ const open = useCallback((items, options) => openNativeMenuWithHost(items, options), []);
241
+ return { available, open };
242
+ }
@@ -0,0 +1,13 @@
1
+ export interface HostServiceRequestOptions {
2
+ signal?: AbortSignal;
3
+ timeoutMs?: number;
4
+ }
5
+ export type HostServiceResponseStatus = 'completed' | 'cancelled' | 'error' | 'timeout';
6
+ export declare class HostServiceRequestError extends Error {
7
+ readonly status: Exclude<HostServiceResponseStatus, 'completed'>;
8
+ readonly code?: string;
9
+ constructor(status: Exclude<HostServiceResponseStatus, 'completed'>, message: string, code?: string);
10
+ }
11
+ export declare function isHostServiceAvailable(name: string): boolean;
12
+ export declare function requestHostService<TResult = unknown>(name: string, payload: unknown, options?: HostServiceRequestOptions): Promise<TResult>;
13
+ //# sourceMappingURL=host-services.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-services.d.ts","sourceRoot":"","sources":["../../src/lib/host-services.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,MAAM,yBAAyB,GACjC,WAAW,GACX,WAAW,GACX,OAAO,GACP,SAAS,CAAA;AAuBb,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,yBAAyB,EAAE,WAAW,CAAC,CAAA;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;gBAGpB,MAAM,EAAE,OAAO,CAAC,yBAAyB,EAAE,WAAW,CAAC,EACvD,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM;CAOhB;AA4GD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM5D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAG,OAAO,EAClD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,OAAO,CAAC,CAiFlB"}