@threadlabs/looma 0.29.3 → 0.29.5

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 (411) hide show
  1. package/editor/mobile-dock.d.ts +29 -0
  2. package/editor/requests.d.ts +5 -26
  3. package/package.json +3 -3
  4. package/styles/ui-action-bar.css +1 -1
  5. package/styles/ui-affordance-scope.css +1 -1
  6. package/styles/ui-avatar-group.css +1 -1
  7. package/styles/ui-avatar.css +1 -1
  8. package/styles/ui-badge.css +1 -1
  9. package/styles/ui-breadcrumb-item.css +1 -1
  10. package/styles/ui-breadcrumbs.css +1 -1
  11. package/styles/ui-button.css +1 -1
  12. package/styles/ui-callout.css +1 -1
  13. package/styles/ui-card.css +1 -1
  14. package/styles/ui-checkbox.css +1 -1
  15. package/styles/ui-cluster.css +1 -1
  16. package/styles/ui-combobox.css +1 -1
  17. package/styles/ui-container.css +1 -1
  18. package/styles/ui-context-menu.css +1 -1
  19. package/styles/ui-cover.css +1 -1
  20. package/styles/ui-description-item.css +1 -1
  21. package/styles/ui-description-list.css +1 -1
  22. package/styles/ui-dialog.css +1 -1
  23. package/styles/ui-disclosure.css +1 -1
  24. package/styles/ui-editable.css +1 -1
  25. package/styles/ui-editor-block-actions.css +1 -1
  26. package/styles/ui-editor-chip-editor.css +1 -1
  27. package/styles/ui-editor-code-language.css +1 -1
  28. package/styles/ui-editor-image-toolbar.css +1 -1
  29. package/styles/ui-editor-insert-table-grid.css +1 -1
  30. package/styles/ui-editor-link-card.css +1 -1
  31. package/styles/ui-editor-link-form.css +1 -1
  32. package/styles/ui-editor-mention-menu-item.css +1 -1
  33. package/styles/ui-editor-mention-menu.css +1 -1
  34. package/styles/ui-editor-slash-menu-group.css +1 -1
  35. package/styles/ui-editor-slash-menu-item.css +1 -1
  36. package/styles/ui-editor-slash-menu.css +1 -1
  37. package/styles/ui-editor-surface.css +1 -1
  38. package/styles/ui-editor-table-context-menu.css +1 -1
  39. package/styles/ui-editor-table-overlay.css +1 -1
  40. package/styles/ui-editor-table-toolbar.css +1 -1
  41. package/styles/ui-editor-toolbar.css +1 -1
  42. package/styles/ui-floating-action-button.css +1 -1
  43. package/styles/ui-form-field.css +1 -1
  44. package/styles/ui-grid.css +1 -1
  45. package/styles/ui-icon-button.css +1 -1
  46. package/styles/ui-icon.css +1 -1
  47. package/styles/ui-image.css +1 -1
  48. package/styles/ui-input-group.css +1 -1
  49. package/styles/ui-input.css +1 -1
  50. package/styles/ui-list-item.css +1 -1
  51. package/styles/ui-list.css +1 -1
  52. package/styles/ui-listbox.css +1 -1
  53. package/styles/ui-menu-group.css +1 -1
  54. package/styles/ui-menu-item.css +1 -1
  55. package/styles/ui-menu.css +1 -1
  56. package/styles/ui-meter.css +1 -1
  57. package/styles/ui-nav-item.css +1 -1
  58. package/styles/ui-page-header.css +1 -1
  59. package/styles/ui-popover.css +1 -1
  60. package/styles/ui-radio-group.css +1 -1
  61. package/styles/ui-radio.css +1 -1
  62. package/styles/ui-reel.css +1 -1
  63. package/styles/ui-scroll-area.css +1 -1
  64. package/styles/ui-search-result-row.css +1 -1
  65. package/styles/ui-search-shell.css +1 -1
  66. package/styles/ui-section.css +1 -1
  67. package/styles/ui-select.css +1 -1
  68. package/styles/ui-separator.css +1 -1
  69. package/styles/ui-sidebar.css +1 -1
  70. package/styles/ui-spinner.css +1 -1
  71. package/styles/ui-stack.css +1 -1
  72. package/styles/ui-status-message.css +1 -1
  73. package/styles/ui-swatch.css +1 -1
  74. package/styles/ui-switch.css +1 -1
  75. package/styles/ui-switcher.css +1 -1
  76. package/styles/ui-table.css +1 -1
  77. package/styles/ui-tabs.css +1 -1
  78. package/styles/ui-text.css +1 -1
  79. package/styles/ui-textarea.css +1 -1
  80. package/styles/ui-toast-region.css +1 -1
  81. package/styles/ui-toast.css +1 -1
  82. package/styles/ui-tooltip.css +1 -1
  83. package/styles/ui-top-bar.css +1 -1
  84. package/styles/ui-tree-item.css +1 -1
  85. package/styles/ui-tree.css +1 -1
  86. package/vanilla/UiActionBar.d.ts +1 -1
  87. package/vanilla/UiActionBar.js +1 -1
  88. package/vanilla/UiAffordanceScope.d.ts +1 -1
  89. package/vanilla/UiAffordanceScope.js +1 -1
  90. package/vanilla/UiAvatar.d.ts +1 -1
  91. package/vanilla/UiAvatar.js +1 -1
  92. package/vanilla/UiAvatarGroup.d.ts +1 -1
  93. package/vanilla/UiAvatarGroup.js +1 -1
  94. package/vanilla/UiBadge.d.ts +1 -1
  95. package/vanilla/UiBadge.js +1 -1
  96. package/vanilla/UiBreadcrumbItem.d.ts +1 -1
  97. package/vanilla/UiBreadcrumbItem.js +1 -1
  98. package/vanilla/UiBreadcrumbs.d.ts +1 -1
  99. package/vanilla/UiBreadcrumbs.js +1 -1
  100. package/vanilla/UiButton.d.ts +1 -1
  101. package/vanilla/UiButton.js +1 -1
  102. package/vanilla/UiCallout.d.ts +1 -1
  103. package/vanilla/UiCallout.js +1 -1
  104. package/vanilla/UiCard.d.ts +1 -1
  105. package/vanilla/UiCard.js +1 -1
  106. package/vanilla/UiCheckbox.d.ts +1 -1
  107. package/vanilla/UiCheckbox.js +1 -1
  108. package/vanilla/UiCluster.d.ts +1 -1
  109. package/vanilla/UiCluster.js +1 -1
  110. package/vanilla/UiCombobox.d.ts +1 -1
  111. package/vanilla/UiCombobox.js +1 -1
  112. package/vanilla/UiContainer.d.ts +1 -1
  113. package/vanilla/UiContainer.js +1 -1
  114. package/vanilla/UiContextMenu.d.ts +1 -1
  115. package/vanilla/UiContextMenu.js +1 -1
  116. package/vanilla/UiCover.d.ts +1 -1
  117. package/vanilla/UiCover.js +1 -1
  118. package/vanilla/UiDescriptionItem.d.ts +1 -1
  119. package/vanilla/UiDescriptionItem.js +1 -1
  120. package/vanilla/UiDescriptionList.d.ts +1 -1
  121. package/vanilla/UiDescriptionList.js +1 -1
  122. package/vanilla/UiDialog.d.ts +1 -1
  123. package/vanilla/UiDialog.js +1 -1
  124. package/vanilla/UiDisclosure.d.ts +1 -1
  125. package/vanilla/UiDisclosure.js +1 -1
  126. package/vanilla/UiEditable.d.ts +1 -1
  127. package/vanilla/UiEditable.js +1 -1
  128. package/vanilla/UiEditorBlockActions.d.ts +1 -1
  129. package/vanilla/UiEditorBlockActions.js +1 -1
  130. package/vanilla/UiEditorChipEditor.d.ts +1 -1
  131. package/vanilla/UiEditorChipEditor.js +1 -1
  132. package/vanilla/UiEditorCodeLanguage.d.ts +1 -1
  133. package/vanilla/UiEditorCodeLanguage.js +1 -1
  134. package/vanilla/UiEditorImageToolbar.d.ts +1 -1
  135. package/vanilla/UiEditorImageToolbar.js +1 -1
  136. package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
  137. package/vanilla/UiEditorInsertTableGrid.js +1 -1
  138. package/vanilla/UiEditorLinkCard.d.ts +1 -1
  139. package/vanilla/UiEditorLinkCard.js +1 -1
  140. package/vanilla/UiEditorLinkForm.d.ts +1 -1
  141. package/vanilla/UiEditorLinkForm.js +1 -1
  142. package/vanilla/UiEditorMentionMenu.d.ts +1 -1
  143. package/vanilla/UiEditorMentionMenu.js +1 -1
  144. package/vanilla/UiEditorMentionMenuItem.d.ts +1 -1
  145. package/vanilla/UiEditorMentionMenuItem.js +1 -1
  146. package/vanilla/UiEditorSlashMenu.d.ts +1 -1
  147. package/vanilla/UiEditorSlashMenu.js +1 -1
  148. package/vanilla/UiEditorSlashMenuGroup.d.ts +1 -1
  149. package/vanilla/UiEditorSlashMenuGroup.js +1 -1
  150. package/vanilla/UiEditorSlashMenuItem.d.ts +1 -1
  151. package/vanilla/UiEditorSlashMenuItem.js +1 -1
  152. package/vanilla/UiEditorSurface.d.ts +1 -1
  153. package/vanilla/UiEditorSurface.js +1 -1
  154. package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
  155. package/vanilla/UiEditorTableContextMenu.js +1 -1
  156. package/vanilla/UiEditorTableOverlay.d.ts +1 -1
  157. package/vanilla/UiEditorTableOverlay.js +1 -1
  158. package/vanilla/UiEditorTableToolbar.d.ts +1 -1
  159. package/vanilla/UiEditorTableToolbar.js +1 -1
  160. package/vanilla/UiEditorToolbar.d.ts +1 -1
  161. package/vanilla/UiEditorToolbar.js +1 -1
  162. package/vanilla/UiFloatingActionButton.d.ts +1 -1
  163. package/vanilla/UiFloatingActionButton.js +1 -1
  164. package/vanilla/UiFormField.d.ts +1 -1
  165. package/vanilla/UiFormField.js +1 -1
  166. package/vanilla/UiGrid.d.ts +1 -1
  167. package/vanilla/UiGrid.js +1 -1
  168. package/vanilla/UiIcon.d.ts +1 -1
  169. package/vanilla/UiIcon.js +1 -1
  170. package/vanilla/UiIconButton.d.ts +1 -1
  171. package/vanilla/UiIconButton.js +1 -1
  172. package/vanilla/UiImage.d.ts +1 -1
  173. package/vanilla/UiImage.js +1 -1
  174. package/vanilla/UiInput.d.ts +1 -1
  175. package/vanilla/UiInput.js +1 -1
  176. package/vanilla/UiInputGroup.d.ts +1 -1
  177. package/vanilla/UiInputGroup.js +1 -1
  178. package/vanilla/UiList.d.ts +1 -1
  179. package/vanilla/UiList.js +1 -1
  180. package/vanilla/UiListItem.d.ts +1 -1
  181. package/vanilla/UiListItem.js +1 -1
  182. package/vanilla/UiListbox.d.ts +1 -1
  183. package/vanilla/UiListbox.js +1 -1
  184. package/vanilla/UiMenu.d.ts +1 -1
  185. package/vanilla/UiMenu.js +1 -1
  186. package/vanilla/UiMenuGroup.d.ts +1 -1
  187. package/vanilla/UiMenuGroup.js +1 -1
  188. package/vanilla/UiMenuItem.d.ts +1 -1
  189. package/vanilla/UiMenuItem.js +1 -1
  190. package/vanilla/UiMeter.d.ts +1 -1
  191. package/vanilla/UiMeter.js +1 -1
  192. package/vanilla/UiNavItem.d.ts +1 -1
  193. package/vanilla/UiNavItem.js +1 -1
  194. package/vanilla/UiPageHeader.d.ts +1 -1
  195. package/vanilla/UiPageHeader.js +1 -1
  196. package/vanilla/UiPopover.d.ts +1 -1
  197. package/vanilla/UiPopover.js +1 -1
  198. package/vanilla/UiRadio.d.ts +1 -1
  199. package/vanilla/UiRadio.js +1 -1
  200. package/vanilla/UiRadioGroup.d.ts +1 -1
  201. package/vanilla/UiRadioGroup.js +1 -1
  202. package/vanilla/UiReel.d.ts +1 -1
  203. package/vanilla/UiReel.js +1 -1
  204. package/vanilla/UiScrollArea.d.ts +1 -1
  205. package/vanilla/UiScrollArea.js +1 -1
  206. package/vanilla/UiSearchResultRow.d.ts +1 -1
  207. package/vanilla/UiSearchResultRow.js +1 -1
  208. package/vanilla/UiSearchShell.d.ts +1 -1
  209. package/vanilla/UiSearchShell.js +1 -1
  210. package/vanilla/UiSection.d.ts +1 -1
  211. package/vanilla/UiSection.js +1 -1
  212. package/vanilla/UiSelect.d.ts +1 -1
  213. package/vanilla/UiSelect.js +1 -1
  214. package/vanilla/UiSeparator.d.ts +1 -1
  215. package/vanilla/UiSeparator.js +1 -1
  216. package/vanilla/UiSidebar.d.ts +1 -1
  217. package/vanilla/UiSidebar.js +1 -1
  218. package/vanilla/UiSpinner.d.ts +1 -1
  219. package/vanilla/UiSpinner.js +1 -1
  220. package/vanilla/UiStack.d.ts +1 -1
  221. package/vanilla/UiStack.js +1 -1
  222. package/vanilla/UiStatusMessage.d.ts +1 -1
  223. package/vanilla/UiStatusMessage.js +1 -1
  224. package/vanilla/UiSwatch.d.ts +1 -1
  225. package/vanilla/UiSwatch.js +1 -1
  226. package/vanilla/UiSwitch.d.ts +1 -1
  227. package/vanilla/UiSwitch.js +1 -1
  228. package/vanilla/UiSwitcher.d.ts +1 -1
  229. package/vanilla/UiSwitcher.js +1 -1
  230. package/vanilla/UiTable.d.ts +1 -1
  231. package/vanilla/UiTable.js +1 -1
  232. package/vanilla/UiTabs.d.ts +1 -1
  233. package/vanilla/UiTabs.js +1 -1
  234. package/vanilla/UiText.d.ts +1 -1
  235. package/vanilla/UiText.js +1 -1
  236. package/vanilla/UiTextarea.d.ts +1 -1
  237. package/vanilla/UiTextarea.js +1 -1
  238. package/vanilla/UiToast.d.ts +1 -1
  239. package/vanilla/UiToast.js +1 -1
  240. package/vanilla/UiToastRegion.d.ts +1 -1
  241. package/vanilla/UiToastRegion.js +1 -1
  242. package/vanilla/UiTooltip.d.ts +1 -1
  243. package/vanilla/UiTooltip.js +1 -1
  244. package/vanilla/UiTopBar.d.ts +1 -1
  245. package/vanilla/UiTopBar.js +1 -1
  246. package/vanilla/UiTree.d.ts +1 -1
  247. package/vanilla/UiTree.js +1 -1
  248. package/vanilla/UiTreeItem.d.ts +1 -1
  249. package/vanilla/UiTreeItem.js +1 -1
  250. package/vue/UiActionBar.vue +1 -1
  251. package/vue/UiAffordanceScope.vue +1 -1
  252. package/vue/UiAvatar.vue +1 -1
  253. package/vue/UiAvatarGroup.vue +1 -1
  254. package/vue/UiBadge.vue +1 -1
  255. package/vue/UiBreadcrumbItem.vue +1 -1
  256. package/vue/UiBreadcrumbs.vue +1 -1
  257. package/vue/UiButton.vue +1 -1
  258. package/vue/UiCallout.vue +1 -1
  259. package/vue/UiCard.vue +1 -1
  260. package/vue/UiCheckbox.vue +1 -1
  261. package/vue/UiCluster.vue +1 -1
  262. package/vue/UiCombobox.vue +1 -1
  263. package/vue/UiContainer.vue +1 -1
  264. package/vue/UiContextMenu.vue +1 -1
  265. package/vue/UiCover.vue +1 -1
  266. package/vue/UiDescriptionItem.vue +1 -1
  267. package/vue/UiDescriptionList.vue +1 -1
  268. package/vue/UiDialog.vue +1 -1
  269. package/vue/UiDisclosure.vue +1 -1
  270. package/vue/UiEditable.vue +1 -1
  271. package/vue/UiEditorBlockActions.vue +1 -1
  272. package/vue/UiEditorChipEditor.vue +1 -1
  273. package/vue/UiEditorCodeLanguage.vue +1 -1
  274. package/vue/UiEditorImageToolbar.vue +1 -1
  275. package/vue/UiEditorInsertTableGrid.vue +1 -1
  276. package/vue/UiEditorLinkCard.vue +1 -1
  277. package/vue/UiEditorLinkForm.vue +1 -1
  278. package/vue/UiEditorMentionMenu.vue +1 -1
  279. package/vue/UiEditorMentionMenuItem.vue +1 -1
  280. package/vue/UiEditorSlashMenu.vue +1 -1
  281. package/vue/UiEditorSlashMenuGroup.vue +1 -1
  282. package/vue/UiEditorSlashMenuItem.vue +1 -1
  283. package/vue/UiEditorSurface.vue +1 -1
  284. package/vue/UiEditorTableContextMenu.vue +1 -1
  285. package/vue/UiEditorTableOverlay.vue +1 -1
  286. package/vue/UiEditorTableToolbar.vue +1 -1
  287. package/vue/UiEditorToolbar.vue +1 -1
  288. package/vue/UiFloatingActionButton.vue +1 -1
  289. package/vue/UiFormField.vue +1 -1
  290. package/vue/UiGrid.vue +1 -1
  291. package/vue/UiIcon.vue +1 -1
  292. package/vue/UiIconButton.vue +1 -1
  293. package/vue/UiImage.vue +1 -1
  294. package/vue/UiInput.vue +1 -1
  295. package/vue/UiInputGroup.vue +1 -1
  296. package/vue/UiList.vue +1 -1
  297. package/vue/UiListItem.vue +1 -1
  298. package/vue/UiListbox.vue +1 -1
  299. package/vue/UiMenu.vue +1 -1
  300. package/vue/UiMenuGroup.vue +1 -1
  301. package/vue/UiMenuItem.vue +1 -1
  302. package/vue/UiMeter.vue +1 -1
  303. package/vue/UiNavItem.vue +1 -1
  304. package/vue/UiPageHeader.vue +1 -1
  305. package/vue/UiPopover.vue +1 -1
  306. package/vue/UiRadio.vue +1 -1
  307. package/vue/UiRadioGroup.vue +1 -1
  308. package/vue/UiReel.vue +1 -1
  309. package/vue/UiScrollArea.vue +1 -1
  310. package/vue/UiSearchResultRow.vue +1 -1
  311. package/vue/UiSearchShell.vue +1 -1
  312. package/vue/UiSection.vue +1 -1
  313. package/vue/UiSelect.vue +1 -1
  314. package/vue/UiSeparator.vue +1 -1
  315. package/vue/UiSidebar.vue +1 -1
  316. package/vue/UiSpinner.vue +1 -1
  317. package/vue/UiStack.vue +1 -1
  318. package/vue/UiStatusMessage.vue +1 -1
  319. package/vue/UiSwatch.vue +1 -1
  320. package/vue/UiSwitch.vue +1 -1
  321. package/vue/UiSwitcher.vue +1 -1
  322. package/vue/UiTable.vue +1 -1
  323. package/vue/UiTabs.vue +1 -1
  324. package/vue/UiText.vue +1 -1
  325. package/vue/UiTextarea.vue +1 -1
  326. package/vue/UiToast.vue +1 -1
  327. package/vue/UiToastRegion.vue +1 -1
  328. package/vue/UiTooltip.vue +1 -1
  329. package/vue/UiTopBar.vue +1 -1
  330. package/vue/UiTree.vue +1 -1
  331. package/vue/UiTreeItem.vue +1 -1
  332. package/vue/chunks/UiActionBar.js +1 -1
  333. package/vue/chunks/UiAffordanceScope.js +1 -1
  334. package/vue/chunks/UiAvatar.js +1 -1
  335. package/vue/chunks/UiAvatarGroup.js +1 -1
  336. package/vue/chunks/UiBadge.js +1 -1
  337. package/vue/chunks/UiBreadcrumbItem.js +1 -1
  338. package/vue/chunks/UiBreadcrumbs.js +1 -1
  339. package/vue/chunks/UiButton.js +1 -1
  340. package/vue/chunks/UiCallout.js +1 -1
  341. package/vue/chunks/UiCard.js +1 -1
  342. package/vue/chunks/UiCheckbox.js +1 -1
  343. package/vue/chunks/UiCluster.js +1 -1
  344. package/vue/chunks/UiCombobox.js +1 -1
  345. package/vue/chunks/UiContainer.js +1 -1
  346. package/vue/chunks/UiContextMenu.js +1 -1
  347. package/vue/chunks/UiCover.js +1 -1
  348. package/vue/chunks/UiDescriptionItem.js +1 -1
  349. package/vue/chunks/UiDescriptionList.js +1 -1
  350. package/vue/chunks/UiDialog.js +1 -1
  351. package/vue/chunks/UiDisclosure.js +1 -1
  352. package/vue/chunks/UiEditable.js +1 -1
  353. package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
  354. package/vue/chunks/UiEditorMentionMenu.js +1 -1
  355. package/vue/chunks/UiEditorMentionMenuItem.js +1 -1
  356. package/vue/chunks/UiEditorSlashMenu.js +1 -1
  357. package/vue/chunks/UiEditorSlashMenuGroup.js +1 -1
  358. package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
  359. package/vue/chunks/UiEditorSurface.js +1 -1
  360. package/vue/chunks/UiEditorTableContextMenu.js +1 -1
  361. package/vue/chunks/UiEditorTableOverlay.js +1 -1
  362. package/vue/chunks/UiEditorTableToolbar.js +1 -1
  363. package/vue/chunks/UiEditorToolbar.js +1 -1
  364. package/vue/chunks/UiFloatingActionButton.js +1 -1
  365. package/vue/chunks/UiFormField.js +1 -1
  366. package/vue/chunks/UiGrid.js +1 -1
  367. package/vue/chunks/UiIcon.js +1 -1
  368. package/vue/chunks/UiIconButton.js +1 -1
  369. package/vue/chunks/UiImage.js +1 -1
  370. package/vue/chunks/UiInput.js +1 -1
  371. package/vue/chunks/UiInputGroup.js +1 -1
  372. package/vue/chunks/UiList.js +1 -1
  373. package/vue/chunks/UiListItem.js +1 -1
  374. package/vue/chunks/UiListbox.js +1 -1
  375. package/vue/chunks/UiMenu.js +1 -1
  376. package/vue/chunks/UiMenuGroup.js +1 -1
  377. package/vue/chunks/UiMenuItem.js +1 -1
  378. package/vue/chunks/UiMeter.js +1 -1
  379. package/vue/chunks/UiNavItem.js +1 -1
  380. package/vue/chunks/UiPageHeader.js +1 -1
  381. package/vue/chunks/UiPopover.js +1 -1
  382. package/vue/chunks/UiRadio.js +1 -1
  383. package/vue/chunks/UiRadioGroup.js +1 -1
  384. package/vue/chunks/UiReel.js +1 -1
  385. package/vue/chunks/UiScrollArea.js +1 -1
  386. package/vue/chunks/UiSearchResultRow.js +1 -1
  387. package/vue/chunks/UiSearchShell.js +1 -1
  388. package/vue/chunks/UiSection.js +1 -1
  389. package/vue/chunks/UiSelect.js +1 -1
  390. package/vue/chunks/UiSeparator.js +1 -1
  391. package/vue/chunks/UiSidebar.js +1 -1
  392. package/vue/chunks/UiSpinner.js +1 -1
  393. package/vue/chunks/UiStack.js +1 -1
  394. package/vue/chunks/UiStatusMessage.js +1 -1
  395. package/vue/chunks/UiSwatch.js +1 -1
  396. package/vue/chunks/UiSwitch.js +1 -1
  397. package/vue/chunks/UiSwitcher.js +1 -1
  398. package/vue/chunks/UiTable.js +1 -1
  399. package/vue/chunks/UiTabs.js +1 -1
  400. package/vue/chunks/UiText.js +1 -1
  401. package/vue/chunks/UiTextarea.js +1 -1
  402. package/vue/chunks/UiToast.js +1 -1
  403. package/vue/chunks/UiToastRegion.js +1 -1
  404. package/vue/chunks/UiTooltip.js +1 -1
  405. package/vue/chunks/UiTopBar.js +1 -1
  406. package/vue/chunks/UiTree.js +1 -1
  407. package/vue/chunks/UiTreeItem.js +1 -1
  408. package/vue/chunks/_plugin-vue_export-helper.js +42 -10
  409. package/vue/components.css +20 -20
  410. package/vue/editor/index.js +189 -85
  411. package/vue/host.ts +83 -30
@@ -1224,7 +1224,7 @@ function createImageUploads(options) {
1224
1224
  };
1225
1225
  }
1226
1226
  //#endregion
1227
- //#region ../../node_modules/.pnpm/@nextwebwg+html-next@1.0.0-alpha.54/node_modules/@nextwebwg/html-next/dist/requests.js
1227
+ //#region ../../node_modules/.pnpm/@nextwebwg+html-next@1.0.0-alpha.55/node_modules/@nextwebwg/html-next/dist/requests.js
1228
1228
  /**
1229
1229
  * Requests: behavior a component asks its consumer for, answered through a native event's
1230
1230
  * `respondWith` (https://nextwebwg.org/declarative-components/javascript#requests).
@@ -1240,7 +1240,12 @@ var port = (event) => {
1240
1240
  if (found === void 0) ports.set(event, found = {});
1241
1241
  return found;
1242
1242
  };
1243
- /** A request as its responders receive it: the nearest one answers with `respondWith`. */
1243
+ /**
1244
+ * A request as its responders receive it: the nearest one answers with `respondWith`. Its static
1245
+ * `respond`, `request` and `hasResponder` are how code without a `host` takes part
1246
+ * (https://nextwebwg.org/declarative-components/javascript#outside-a-controller). They never read
1247
+ * `this`, so `const { respond, request, hasResponder } = RequestEvent` works.
1248
+ */
1244
1249
  var RequestEvent = class extends CustomEvent {
1245
1250
  /** Aborts when the asker no longer needs the answer, or its component disconnects. */
1246
1251
  signal;
@@ -1264,71 +1269,135 @@ var RequestEvent = class extends CustomEvent {
1264
1269
  reportError(error);
1265
1270
  }
1266
1271
  }
1267
- };
1268
- //#endregion
1269
- //#region src/editor/requests.ts
1270
- var AskedRequest = class extends RequestEvent {
1271
- answered = false;
1272
- answer;
1273
- report;
1274
- respondWith(answer) {
1275
- super.respondWith(answer);
1276
- this.answered = true;
1277
- this.answer = answer;
1272
+ /**
1273
+ * Answers `name` requests that reach `target` with `answer`, records it as a known responder, then
1274
+ * announces it so a component whose request went unanswered can ask again. Returns a function that
1275
+ * removes it.
1276
+ */
1277
+ static respond(target, name, answer) {
1278
+ const listener = (event) => {
1279
+ if ("respondWith" in event) answerRequest(event, answer);
1280
+ };
1281
+ target.addEventListener(name, listener);
1282
+ const forget = knownResponder(target, name);
1283
+ target.dispatchEvent(new CustomEvent("responder", {
1284
+ bubbles: true,
1285
+ detail: { name }
1286
+ }));
1287
+ return () => {
1288
+ target.removeEventListener(name, listener);
1289
+ forget();
1290
+ };
1278
1291
  }
1279
- progress(loaded, total) {
1280
- if (this.signal.aborted) return;
1281
- try {
1282
- this.report?.(loaded, total);
1283
- } catch (error) {
1284
- reportError(error);
1285
- }
1292
+ /**
1293
+ * Asks `name` at `target` with the request steps `host.request` uses, with no declaration to check
1294
+ * the detail or the answer against, no connection signal, and nothing remembered for late responders.
1295
+ */
1296
+ static request(target, name, detail, options) {
1297
+ return dispatchRequest(target, target.nodeType ? target : null, name, detail ?? null, options?.signal ?? new AbortController().signal, options?.progress);
1298
+ }
1299
+ /** Whether a known responder for `name` is on the path a request from `target` takes, now. */
1300
+ static hasResponder(target, name) {
1301
+ return knownCount(target, name) > 0;
1286
1302
  }
1287
1303
  };
1288
- /** Settles with `answer`, or rejects with the signal's reason when it aborts first. */
1289
- var settle = (answer, signal) => new Promise((resolve, reject) => {
1290
- const abort = () => reject(signal.reason);
1291
- if (signal.aborted) abort();
1292
- signal.addEventListener("abort", abort, { once: true });
1293
- Promise.resolve(answer).then((value) => {
1294
- signal.removeEventListener("abort", abort);
1295
- resolve(value);
1296
- }, (error) => {
1297
- signal.removeEventListener("abort", abort);
1298
- reject(error);
1304
+ /** Answers a request event with a responder function, as `RequestEvent.respond` and framework function props do. */
1305
+ function answerRequest(event, responder) {
1306
+ const request = event;
1307
+ request.respondWith(responder(request.detail, {
1308
+ signal: request.signal,
1309
+ progress: (loaded, total) => request.progress(loaded, total)
1310
+ }));
1311
+ }
1312
+ var runtimeKey = Symbol.for("@nextwebwg/html-next.runtime.v1");
1313
+ var documentRecord = (document) => document[runtimeKey] ??= {};
1314
+ /** A target's document: a node's owner, a window's document, or a target outside the DOM itself. */
1315
+ var recordOf = (target) => documentRecord(target.nodeType === 9 ? target : target.ownerDocument ?? target.document ?? target);
1316
+ var requestState = (record) => record.requests ??= { g: /* @__PURE__ */ new WeakMap() };
1317
+ /**
1318
+ * Records a responder for `name` on `target` that `hasResponder` can see, until the returned function
1319
+ * runs. `own` counts the entries a controller's `host.on` adds on its own root, which its own
1320
+ * `host.hasResponder` does not count.
1321
+ */
1322
+ function knownResponder(target, name, own) {
1323
+ const record = recordOf(target);
1324
+ const known = record.k ??= /* @__PURE__ */ new WeakMap();
1325
+ const names = known.get(target) ?? known.set(target, []).get(target);
1326
+ const change = (add) => {
1327
+ for (const list of own === void 0 ? [names] : [names, own]) if (add) list.push(name);
1328
+ else list.splice(list.indexOf(name), 1);
1329
+ record.w?.forEach((changed) => changed(name));
1330
+ };
1331
+ change(true);
1332
+ let held = true;
1333
+ return () => {
1334
+ if (held) {
1335
+ held = false;
1336
+ change(false);
1337
+ }
1338
+ };
1339
+ }
1340
+ /** The next object on a composed event's path: an assigned slot, a parent, a shadow host, the window. */
1341
+ var parentOf = (node) => node.nodeType === 9 ? node.defaultView : node.nodeType === 11 ? node.host : node.nodeType ? node.assignedSlot ?? node.parentNode : null;
1342
+ /** How many of `names` are `name`. */
1343
+ var countOf = (names, name) => names?.filter((known) => known === name).length ?? 0;
1344
+ /** How many known responders for `name` are on the path a request from `target` takes. */
1345
+ function knownCount(target, name) {
1346
+ const known = recordOf(target).k;
1347
+ let count = 0;
1348
+ if (known !== void 0) for (let node = target; node; node = parentOf(node)) count += countOf(known.get(node), name);
1349
+ return count;
1350
+ }
1351
+ /** Settles with `value`, or rejects with the signal's reason when it aborts first; a late value is discarded. */
1352
+ function settle(value, signal) {
1353
+ return new Promise((resolve, reject) => {
1354
+ const abort = () => reject(signal.reason);
1355
+ if (signal.aborted) abort();
1356
+ signal.addEventListener("abort", abort, { once: true });
1357
+ Promise.resolve(value).then((result) => {
1358
+ signal.removeEventListener("abort", abort);
1359
+ resolve(result);
1360
+ }, (error) => {
1361
+ signal.removeEventListener("abort", abort);
1362
+ reject(error);
1363
+ });
1299
1364
  });
1300
- });
1365
+ }
1301
1366
  /**
1302
- * Asks `name` at `root` as an HTML Next component's `host.request` does: dispatches a bubbling,
1303
- * composed `RequestEvent`, and the nearest responder's answer settles it. A responder that answers
1304
- * with a value, or no responder at all, settles it at once, so the answer is returned as it is; an
1305
- * answer given as a promise is returned as a promise.
1306
- *
1307
- * @contract Settles `null` when no listener answers during the dispatch, or when the answer is `null`.
1308
- * @failure Throws when the signal has already aborted. A promised answer rejects with the signal's
1309
- * reason when it aborts before the answer arrives, and with the answer's own rejection.
1367
+ * The request steps every asker shares: wait for the controllers of components at `from` and around
1368
+ * it, dispatch the `RequestEvent` at `target`, and settle with the answer, or `null` when nobody
1369
+ * answered. `answered` hears, during the dispatch, whether anyone did.
1310
1370
  */
1311
- function askRequest(root, name, detail, options = {}) {
1312
- const signal = options.signal ?? new AbortController().signal;
1371
+ async function dispatchRequest(target, from, name, detail, signal, progress, answered) {
1313
1372
  signal.throwIfAborted();
1314
- const event = new AskedRequest(name, {
1315
- detail: detail ?? null,
1373
+ const state = requestState(recordOf(target));
1374
+ for (;;) {
1375
+ const waits = [];
1376
+ for (let node = from; node !== null; node = node.parentNode ?? node.host ?? null) {
1377
+ const gate = state.g.get(node);
1378
+ if (gate !== void 0) waits.push(gate);
1379
+ }
1380
+ if (waits.length === 0) break;
1381
+ await settle(Promise.all(waits), signal);
1382
+ }
1383
+ const event = new RequestEvent(name, {
1384
+ detail,
1316
1385
  signal,
1317
1386
  bubbles: true,
1318
1387
  composed: true
1319
1388
  });
1320
- event.report = options.progress;
1321
- root.dispatchEvent(event);
1322
- const answer = event.answered ? event.answer : null;
1323
- if (!isThenable(answer)) {
1324
- event.report = void 0;
1325
- return answer ?? null;
1389
+ const recorded = port(event);
1390
+ recorded.p = progress;
1391
+ target.dispatchEvent(event);
1392
+ answered?.(recorded.a !== void 0);
1393
+ try {
1394
+ return recorded.a === void 0 ? null : await settle(recorded.a[0], signal);
1395
+ } finally {
1396
+ recorded.p = void 0;
1326
1397
  }
1327
- return settle(answer, signal).then((value) => value ?? null).finally(() => {
1328
- event.report = void 0;
1329
- });
1330
1398
  }
1331
- var isThenable = (value) => typeof value?.then === "function";
1399
+ //#endregion
1400
+ //#region src/editor/requests.ts
1332
1401
  /** Answers a request event with a responder function, as an HTML Next framework function prop does. */
1333
1402
  function respondWithFunction(event, responder) {
1334
1403
  const request = event;
@@ -1338,8 +1407,8 @@ function respondWithFunction(event, responder) {
1338
1407
  }));
1339
1408
  }
1340
1409
  /**
1341
- * Calls `callback` with the request name when a responder announces itself, as HTML Next's
1342
- * `respond()` does, on `root`, one of its ancestors, or the document.
1410
+ * Calls `callback` with the request name when a responder announces itself, as
1411
+ * `RequestEvent.respond()` does, on `root`, one of its ancestors, or the document.
1343
1412
  *
1344
1413
  * @lifecycle Listens on the document until the returned function is called.
1345
1414
  */
@@ -1810,6 +1879,45 @@ function selectionActionDetail(state, id) {
1810
1879
  after: doc.textBetween(to, Math.min(doc.content.size, to + CONTEXT), "\n")
1811
1880
  };
1812
1881
  }
1882
+ /** Whether a viewport this wide gets the editing dock rather than floating tools. */
1883
+ var usesMobileDock = (viewportWidth) => viewportWidth <= 767;
1884
+ /**
1885
+ * Where the dock sits: across the visual viewport, against its bottom edge, so an on-screen keyboard
1886
+ * pushes it up. It never rises above the viewport's top.
1887
+ */
1888
+ function mobileDockPlacement(viewport, dockHeight) {
1889
+ return {
1890
+ left: viewport.left,
1891
+ top: Math.max(viewport.top, viewport.bottom - dockHeight),
1892
+ width: viewport.width
1893
+ };
1894
+ }
1895
+ /** Calls `onChange` with the new mode whenever it changes. */
1896
+ function createMobileDock(onChange) {
1897
+ let mode = "formatting";
1898
+ let formattingChosen = false;
1899
+ const set = (next) => {
1900
+ if (next === mode) return;
1901
+ mode = next;
1902
+ onChange(mode);
1903
+ };
1904
+ return {
1905
+ get mode() {
1906
+ return mode;
1907
+ },
1908
+ tableActive() {
1909
+ if (!formattingChosen) set("table");
1910
+ },
1911
+ showFormatting() {
1912
+ formattingChosen = true;
1913
+ set("formatting");
1914
+ },
1915
+ tableInactive() {
1916
+ formattingChosen = false;
1917
+ set("formatting");
1918
+ }
1919
+ };
1920
+ }
1813
1921
  //#endregion
1814
1922
  //#region src/editor/extensions/relative-links.ts
1815
1923
  /** Keep other origins and non-web schemes intact; same-origin links retain path, query, and fragment. */
@@ -3508,7 +3616,7 @@ var LoomaEditor = defineComponent({
3508
3616
  });
3509
3617
  const tablePickerOpen = ref(false);
3510
3618
  const mobileToolbarStyle = ref({});
3511
- const mobile = ref(typeof window !== "undefined" && window.innerWidth <= 767);
3619
+ const mobile = ref(typeof window !== "undefined" && usesMobileDock(window.innerWidth));
3512
3620
  const editorFocused = ref(false);
3513
3621
  let formatting;
3514
3622
  let formattingPopup = null;
@@ -3520,10 +3628,12 @@ var LoomaEditor = defineComponent({
3520
3628
  const formattingActive = () => formatting?.active() ?? false;
3521
3629
  const editorStateVersion = ref(0);
3522
3630
  const mobileToolbarMode = ref("formatting");
3631
+ const mobileDock = createMobileDock((mode) => {
3632
+ mobileToolbarMode.value = mode;
3633
+ });
3523
3634
  let dragLeaveTimer = null;
3524
3635
  let tableResizeActive = false;
3525
3636
  let tableInteractionActive = false;
3526
- let mobileTableControlsDismissed = false;
3527
3637
  let hoveredTableCell = null;
3528
3638
  let overlayTableElement = null;
3529
3639
  let tablePointerFrame = null;
@@ -3573,16 +3683,17 @@ var LoomaEditor = defineComponent({
3573
3683
  chipEditing?.close();
3574
3684
  if (focusChip) element?.focus();
3575
3685
  };
3576
- const found = reactive(/* @__PURE__ */ new Set());
3686
+ const responderVersion = ref(0);
3577
3687
  const answers = (name) => {
3688
+ responderVersion.value;
3578
3689
  const prop = EDITOR_REQUESTS[name];
3579
- return typeof props[prop] === "function" || attrs[`on${prop[0].toUpperCase()}${prop.slice(1)}`] != null || found.has(name);
3690
+ return typeof props[prop] === "function" || attrs[`on${prop[0].toUpperCase()}${prop.slice(1)}`] != null || root.value !== null && RequestEvent.hasResponder(root.value, name);
3580
3691
  };
3581
3692
  const connection = new AbortController();
3582
3693
  const ask = (name, detail, options = {}) => {
3583
- if (!root.value || connection.signal.aborted) return null;
3694
+ if (!root.value || connection.signal.aborted) return Promise.resolve(null);
3584
3695
  const signal = options.signal ? AbortSignal.any([options.signal, connection.signal]) : connection.signal;
3585
- return askRequest(root.value, name, detail, {
3696
+ return RequestEvent.request(root.value, name, detail, {
3586
3697
  ...options,
3587
3698
  signal
3588
3699
  });
@@ -3596,10 +3707,12 @@ var LoomaEditor = defineComponent({
3596
3707
  };
3597
3708
  const askThen = (name, detail, apply) => {
3598
3709
  const answer = askLatest(name, detail);
3599
- if (!(answer instanceof Promise)) return apply(answer);
3600
3710
  const controller = latest.get(name);
3601
- answer.then(apply, (error) => {
3602
- if (controller !== latest.get(name) || connection.signal.aborted) return;
3711
+ const current = () => controller === latest.get(name) && !connection.signal.aborted;
3712
+ answer.then((value) => {
3713
+ if (current()) apply(value);
3714
+ }, (error) => {
3715
+ if (!current()) return;
3603
3716
  reportError(error);
3604
3717
  apply(null);
3605
3718
  });
@@ -3794,14 +3907,7 @@ var LoomaEditor = defineComponent({
3794
3907
  chipEditing = chips;
3795
3908
  const imageUploads = createImageUploads({
3796
3909
  editor: session.editor,
3797
- upload: () => async (file, init) => {
3798
- const image = await ask("image-upload", { file }, init);
3799
- if (image && !found.has("image-upload")) {
3800
- found.add("image-upload");
3801
- checkResponders();
3802
- }
3803
- return image;
3804
- },
3910
+ upload: () => (file, init) => ask("image-upload", { file }, init),
3805
3911
  onError: (error, file) => emit("uploadError", error, file)
3806
3912
  });
3807
3913
  imageUploads.subscribe(() => {
@@ -3838,9 +3944,10 @@ var LoomaEditor = defineComponent({
3838
3944
  }, { capture: true });
3839
3945
  stopAnnouncements = onResponderAnnounced(element, (name) => {
3840
3946
  if (!(name in EDITOR_REQUESTS)) return;
3841
- found.add(name);
3947
+ responderVersion.value += 1;
3842
3948
  checkResponders();
3843
3949
  });
3950
+ responderVersion.value += 1;
3844
3951
  responders = new Set(EDITOR_REQUEST_NAMES.filter(answers));
3845
3952
  askExtensions();
3846
3953
  askSlashCommands();
@@ -3993,22 +4100,20 @@ var LoomaEditor = defineComponent({
3993
4100
  tableUi.geometry = null;
3994
4101
  tableUi.capabilities = { ...EMPTY_CAPABILITIES };
3995
4102
  overlayTableElement = null;
3996
- mobileTableControlsDismissed = false;
3997
- mobileToolbarMode.value = "formatting";
4103
+ mobileDock.tableInactive();
3998
4104
  };
3999
4105
  const updateMobileViewport = () => {
4000
- mobile.value = window.innerWidth <= 767;
4106
+ mobile.value = usesMobileDock(window.innerWidth);
4001
4107
  if (!mobile.value) {
4002
4108
  mobileToolbarStyle.value = {};
4003
4109
  return;
4004
4110
  }
4005
4111
  nextTick(() => {
4006
- const viewport = getVisualViewportRect(window);
4007
- const toolbarHeight = mobileToolbarShell.value?.getBoundingClientRect().height || 56;
4112
+ const placement = mobileDockPlacement(getVisualViewportRect(window), mobileToolbarShell.value?.getBoundingClientRect().height || 56);
4008
4113
  mobileToolbarStyle.value = {
4009
- left: `${viewport.left}px`,
4010
- top: `${Math.max(viewport.top, viewport.bottom - toolbarHeight)}px`,
4011
- width: `${viewport.width}px`
4114
+ left: `${placement.left}px`,
4115
+ top: `${placement.top}px`,
4116
+ width: `${placement.width}px`
4012
4117
  };
4013
4118
  });
4014
4119
  };
@@ -4098,7 +4203,7 @@ var LoomaEditor = defineComponent({
4098
4203
  }
4099
4204
  const selectedTableIsActive = state.active && selectedTable === table;
4100
4205
  overlayTableElement = table;
4101
- if (selectedTableIsActive && !mobileTableControlsDismissed) mobileToolbarMode.value = "table";
4206
+ if (selectedTableIsActive) mobileDock.tableActive();
4102
4207
  const rect = table.getBoundingClientRect();
4103
4208
  const maxToolbarWidth = Math.min(420, window.innerWidth - 24);
4104
4209
  const toolbarLeft = Math.min(Math.max(12, rect.left + (rect.width - maxToolbarWidth) / 2), Math.max(12, window.innerWidth - maxToolbarWidth - 12));
@@ -4853,8 +4958,7 @@ var LoomaEditor = defineComponent({
4853
4958
  type: "button",
4854
4959
  "aria-label": "Formatting tools",
4855
4960
  onClick: () => {
4856
- mobileTableControlsDismissed = true;
4857
- mobileToolbarMode.value = "formatting";
4961
+ mobileDock.showFormatting();
4858
4962
  editor.value?.commands.focus();
4859
4963
  nextTick(updateMobileViewport);
4860
4964
  }
package/vue/host.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Generated by HTML Next 1.0.0-alpha.54 for Vue 3.5. Do not edit.
1
+ // Generated by HTML Next 1.0.0-alpha.55 for Vue 3.5. Do not edit.
2
2
  import {
3
3
  computed,
4
4
  createTextVNode,
@@ -206,6 +206,8 @@ const requestStateKey = Symbol.for('@nextwebwg/html-next.runtime.v1')
206
206
  type DocumentRecord = {
207
207
  requests?: { readonly g: WeakMap<Node, Promise<void>> }
208
208
  relay?: (from: Node, name: string) => void
209
+ k?: WeakMap<EventTarget, string[]>
210
+ w?: Set<(name: string) => void>
209
211
  }
210
212
  const documentRecord = (root: Element): DocumentRecord =>
211
213
  (root.ownerDocument as unknown as Record<symbol, DocumentRecord>)[requestStateKey] ??= {}
@@ -229,6 +231,28 @@ function relayResponders(root: Element, name: string): void {
229
231
  documentRecord(root).relay?.(root, name)
230
232
  }
231
233
 
234
+ /** Records a responder hasResponder can see on root until the returned function runs; own lists its controller's. */
235
+ function knownResponder(root: Element, name: string, own?: string[]): () => void {
236
+ const record = documentRecord(root)
237
+ const known = record.k ??= new WeakMap()
238
+ const names = known.get(root) ?? known.set(root, []).get(root)!
239
+ const change = (add: boolean): void => {
240
+ for (const list of own === undefined ? [names] : [names, own]) {
241
+ if (add) list.push(name)
242
+ else list.splice(list.indexOf(name), 1)
243
+ }
244
+ record.w?.forEach((changed) => changed(name))
245
+ }
246
+ change(true)
247
+ let held = true
248
+ return () => {
249
+ if (held) {
250
+ held = false
251
+ change(false)
252
+ }
253
+ }
254
+ }
255
+
232
256
  /** For a component that asks: a responder announcement reaches its controller only as the relay to its root, which does not bubble. */
233
257
  function hostListener(type: string, callback: (event: Event) => unknown): (event: Event) => void {
234
258
  return (event) => {
@@ -538,14 +562,16 @@ export interface ComponentHostOptions {
538
562
  /** Each named declared script, which a controller reads as `host.scripts`. */
539
563
  readonly scripts?: Readonly<Record<string, unknown>>
540
564
  readonly acceptsState?: (name: string, keys: readonly string[], value: unknown) => boolean
541
- /** Asks one of the component's declared requests. */
542
- request?(
543
- root: Element,
544
- connection: AbortSignal,
545
- name: string,
546
- detail?: unknown,
547
- options?: unknown,
548
- ): Promise<unknown>
565
+ /** Asks one of the component's declared requests; its `has` builds `host.hasResponder`. */
566
+ readonly request?:
567
+ & ((
568
+ root: Element,
569
+ connection: AbortSignal,
570
+ name: string,
571
+ detail?: unknown,
572
+ options?: any,
573
+ ) => Promise<unknown>)
574
+ & { readonly has?: (host: any, own: string[]) => (name: string) => boolean }
549
575
  /** Each declared request's responder, from its function prop or event form, read when the request arrives. */
550
576
  readonly responders?: Readonly<Record<string, () => ((event: Event) => void) | undefined>>
551
577
  }
@@ -632,20 +658,30 @@ export function useComponentHost(
632
658
  const stops: Array<() => void> = []
633
659
  const connected = shallowRef(false)
634
660
  const pauses = new Map<() => void, () => void>()
635
- const subscriptions = new Set<
636
- {
637
- type: string
638
- callback: (event: Event) => void | (() => void)
639
- target?: Element | undefined
640
- cleanup?: void | (() => void)
641
- }
642
- >()
661
+ // A subscription's known responder (k), and for a request's function prop or event form whether one is set (r).
662
+ const subscriptions = new Set<{
663
+ type: string
664
+ callback: (event: Event) => void | (() => void)
665
+ target?: Element | undefined
666
+ cleanup?: void | (() => void)
667
+ k?: (() => void) | undefined
668
+ r?: () => boolean
669
+ }>()
643
670
  type Subscription = typeof subscriptions extends Set<infer S> ? S : never
671
+ // How many known responders the controller's host.on keeps on its own root, by name.
672
+ const own: string[] = []
673
+ const track = (entry: Subscription): void => {
674
+ entry.k?.()
675
+ entry.k = entry.target === undefined || entry.r?.() === false
676
+ ? undefined
677
+ : knownResponder(entry.target, entry.type, entry.r ? undefined : own)
678
+ }
644
679
  const activate = (entry: Subscription): void => {
645
680
  if (entry.type === 'connect') entry.cleanup = entry.callback(new Event('connect'))
646
681
  else if (entry.type !== 'disconnect') {
647
682
  entry.target = root.value ?? undefined
648
683
  entry.target?.addEventListener(entry.type, entry.callback as EventListener)
684
+ track(entry)
649
685
  // A responder registered after a request went unanswered tells the asker to ask again.
650
686
  if (entry.target !== undefined) relayResponders(entry.target, entry.type)
651
687
  }
@@ -653,6 +689,7 @@ export function useComponentHost(
653
689
  const deactivate = (entry: Subscription, disconnecting: boolean): void => {
654
690
  entry.target?.removeEventListener(entry.type, entry.callback as EventListener)
655
691
  entry.target = undefined
692
+ track(entry)
656
693
  const cleanup = entry.cleanup
657
694
  entry.cleanup = undefined
658
695
  cleanup?.()
@@ -704,17 +741,7 @@ export function useComponentHost(
704
741
  }, options.controllerSource?.definition ?? '<component>'),
705
742
  scripts: options.scripts ?? Object.freeze({}),
706
743
  on(type: string, callback: (event: Event) => void | (() => void)): () => void {
707
- const entry: Subscription = {
708
- type,
709
- callback: type === 'connect' || type === 'disconnect' || options.request === undefined
710
- ? callback
711
- : hostListener(type, callback),
712
- }
713
- subscriptions.add(entry)
714
- if (connected.value) activate(entry)
715
- return () => {
716
- if (subscriptions.delete(entry)) deactivate(entry, false)
717
- }
744
+ return listen(type, callback)
718
745
  },
719
746
  props: Object.freeze(propHandles),
720
747
  refs: Object.defineProperties(
@@ -787,13 +814,39 @@ export function useComponentHost(
787
814
  ),
788
815
  }),
789
816
  }
817
+ function listen(
818
+ type: string,
819
+ callback: (event: Event) => void | (() => void),
820
+ set?: () => boolean,
821
+ ): () => void {
822
+ const entry: Subscription = {
823
+ type,
824
+ callback: type === 'connect' || type === 'disconnect' || options.request === undefined
825
+ ? callback
826
+ : hostListener(type, callback),
827
+ }
828
+ if (set !== undefined) entry.r = set
829
+ subscriptions.add(entry)
830
+ if (connected.value) activate(entry)
831
+ return () => {
832
+ if (subscriptions.delete(entry)) deactivate(entry, false)
833
+ }
834
+ }
835
+ if (options.request?.has !== undefined) {
836
+ Object.assign(host, { hasResponder: options.request.has(host, own) })
837
+ }
790
838
  const requests = requestConnection()
791
839
  // Each request's responder listens on the root from its first connection, before the controller runs.
792
840
  const responders = Object.entries(options.responders ?? {})
793
- for (const [name, read] of responders) host.on(name, (event) => read()?.(event))
794
- // A function prop or event form set later relays for its request, as a late host.on does.
841
+ for (const [name, read] of responders) {
842
+ listen(name, (event) =>
843
+ read()?.(event), () =>
844
+ read() !== undefined)
845
+ }
846
+ // A function prop or event form set later is a known responder, and relays for its request, as a late host.on does.
795
847
  if (responders.length > 0) {
796
848
  watch(() => responders.map(([, read]) => read() !== undefined), (now, before) => {
849
+ for (const entry of subscriptions) if (entry.r !== undefined) track(entry)
797
850
  const element = root.value
798
851
  if (element === null || !connected.value) return
799
852
  now.forEach((set, index) => {