@threadlabs/looma 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (508) hide show
  1. package/components/shared/trigger.js +9 -4
  2. package/components/ui-affordance-scope/ui-affordance-scope.html +1 -1
  3. package/components/ui-avatar/ui-avatar.html +2 -2
  4. package/components/ui-avatar-group/ui-avatar-group.html +1 -1
  5. package/components/ui-avatar-group/ui-avatar-group.js +1 -1
  6. package/components/ui-badge/ui-badge.html +3 -3
  7. package/components/ui-button/ui-button.html +7 -6
  8. package/components/ui-callout/ui-callout.html +1 -1
  9. package/components/ui-card/ui-card.html +5 -4
  10. package/components/ui-checkbox/ui-checkbox.html +6 -2
  11. package/components/ui-cluster/ui-cluster.html +4 -4
  12. package/components/ui-combobox/ui-combobox.html +257 -34
  13. package/components/ui-combobox/ui-combobox.js +21 -20
  14. package/components/ui-container/ui-container.html +2 -2
  15. package/components/ui-context-menu/ui-context-menu.html +17 -5
  16. package/components/ui-cover/ui-cover.html +1 -1
  17. package/components/ui-description-list/ui-description-list.html +3 -3
  18. package/components/ui-dialog/ui-dialog.html +14 -6
  19. package/components/ui-disclosure/ui-disclosure.html +14 -5
  20. package/components/ui-editable/ui-editable.html +15 -4
  21. package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +1 -1
  22. package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +1 -1
  23. package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +26 -6
  24. package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +90 -12
  25. package/components/ui-editor-table-overlay/ui-editor-table-overlay.js +5 -5
  26. package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +33 -7
  27. package/components/ui-grid/ui-grid.html +2 -2
  28. package/components/ui-icon-button/ui-icon-button.html +2 -2
  29. package/components/ui-input/ui-input.html +28 -6
  30. package/components/ui-list/ui-list.html +5 -4
  31. package/components/ui-list-item/ui-list-item.html +1 -1
  32. package/components/ui-listbox/ui-listbox.html +7 -1
  33. package/components/ui-menu/ui-menu.html +18 -5
  34. package/components/ui-menu-item/ui-menu-item.html +7 -2
  35. package/components/ui-meter/ui-meter.html +2 -2
  36. package/components/ui-nav-item/ui-nav-item.html +5 -4
  37. package/components/ui-page-header/ui-page-header.html +1 -1
  38. package/components/ui-popover/ui-popover.html +14 -5
  39. package/components/ui-radio/ui-radio.html +6 -2
  40. package/components/ui-radio-group/ui-radio-group.html +11 -3
  41. package/components/ui-reel/ui-reel.html +3 -3
  42. package/components/ui-scroll-area/ui-scroll-area.html +1 -1
  43. package/components/ui-search-shell/ui-search-shell.html +6 -2
  44. package/components/ui-section/ui-section.html +2 -2
  45. package/components/ui-select/ui-select.html +1 -1
  46. package/components/ui-separator/ui-separator.html +1 -1
  47. package/components/ui-sidebar/ui-sidebar.html +11 -4
  48. package/components/ui-spinner/ui-spinner.html +1 -1
  49. package/components/ui-stack/ui-stack.html +3 -3
  50. package/components/ui-status-message/ui-status-message.html +2 -2
  51. package/components/ui-switch/ui-switch.html +6 -2
  52. package/components/ui-switcher/ui-switcher.html +3 -3
  53. package/components/ui-table/ui-table.html +1 -1
  54. package/components/ui-tabs/ui-tabs.html +9 -4
  55. package/components/ui-text/ui-text.html +6 -6
  56. package/components/ui-textarea/ui-textarea.html +1 -1
  57. package/components/ui-toast/ui-toast.html +6 -2
  58. package/components/ui-toast-region/ui-toast-region.html +16 -4
  59. package/components/ui-tooltip/ui-tooltip.html +15 -6
  60. package/components/ui-tree/ui-tree.html +30 -7
  61. package/components/ui-tree-item/ui-tree-item.html +10 -6
  62. package/components/ui-tree-item/ui-tree-item.js +20 -3
  63. package/dist/index.js +1 -1
  64. package/editor/table-overlay.d.ts +1 -1
  65. package/package.json +3 -3
  66. package/styles/ui-action-bar.css +1 -1
  67. package/styles/ui-affordance-scope.css +1 -1
  68. package/styles/ui-avatar-group.css +1 -1
  69. package/styles/ui-avatar.css +1 -1
  70. package/styles/ui-badge.css +1 -1
  71. package/styles/ui-breadcrumb-item.css +1 -1
  72. package/styles/ui-breadcrumbs.css +1 -1
  73. package/styles/ui-button.css +1 -1
  74. package/styles/ui-callout.css +1 -1
  75. package/styles/ui-card.css +1 -1
  76. package/styles/ui-checkbox.css +1 -1
  77. package/styles/ui-cluster.css +1 -1
  78. package/styles/ui-combobox.css +1 -1
  79. package/styles/ui-container.css +1 -1
  80. package/styles/ui-context-menu.css +1 -1
  81. package/styles/ui-cover.css +1 -1
  82. package/styles/ui-description-item.css +1 -1
  83. package/styles/ui-description-list.css +1 -1
  84. package/styles/ui-dialog.css +1 -1
  85. package/styles/ui-disclosure.css +1 -1
  86. package/styles/ui-editable.css +1 -1
  87. package/styles/ui-editor-insert-table-grid.css +1 -1
  88. package/styles/ui-editor-mention-menu-item.css +1 -1
  89. package/styles/ui-editor-mention-menu.css +1 -1
  90. package/styles/ui-editor-slash-menu-group.css +1 -1
  91. package/styles/ui-editor-slash-menu-item.css +1 -1
  92. package/styles/ui-editor-slash-menu.css +1 -1
  93. package/styles/ui-editor-table-context-menu.css +1 -1
  94. package/styles/ui-editor-table-overlay.css +1 -1
  95. package/styles/ui-editor-table-toolbar.css +1 -1
  96. package/styles/ui-editor-toolbar.css +1 -1
  97. package/styles/ui-floating-action-button.css +1 -1
  98. package/styles/ui-form-field.css +1 -1
  99. package/styles/ui-grid.css +1 -1
  100. package/styles/ui-icon-button.css +1 -1
  101. package/styles/ui-icon.css +1 -1
  102. package/styles/ui-input-group.css +1 -1
  103. package/styles/ui-input.css +1 -1
  104. package/styles/ui-list-item.css +1 -1
  105. package/styles/ui-list.css +1 -1
  106. package/styles/ui-listbox.css +1 -1
  107. package/styles/ui-menu-group.css +1 -1
  108. package/styles/ui-menu-item.css +1 -1
  109. package/styles/ui-menu.css +1 -1
  110. package/styles/ui-meter.css +1 -1
  111. package/styles/ui-nav-item.css +1 -1
  112. package/styles/ui-page-header.css +1 -1
  113. package/styles/ui-popover.css +1 -1
  114. package/styles/ui-radio-group.css +1 -1
  115. package/styles/ui-radio.css +1 -1
  116. package/styles/ui-reel.css +1 -1
  117. package/styles/ui-scroll-area.css +1 -1
  118. package/styles/ui-search-result-row.css +1 -1
  119. package/styles/ui-search-shell.css +1 -1
  120. package/styles/ui-section.css +1 -1
  121. package/styles/ui-select.css +1 -1
  122. package/styles/ui-separator.css +1 -1
  123. package/styles/ui-sidebar.css +1 -1
  124. package/styles/ui-spinner.css +1 -1
  125. package/styles/ui-stack.css +1 -1
  126. package/styles/ui-status-message.css +1 -1
  127. package/styles/ui-switch.css +1 -1
  128. package/styles/ui-switcher.css +1 -1
  129. package/styles/ui-table.css +1 -1
  130. package/styles/ui-tabs.css +1 -1
  131. package/styles/ui-text.css +1 -1
  132. package/styles/ui-textarea.css +1 -1
  133. package/styles/ui-toast-region.css +1 -1
  134. package/styles/ui-toast.css +1 -1
  135. package/styles/ui-tooltip.css +1 -1
  136. package/styles/ui-top-bar.css +1 -1
  137. package/styles/ui-tree-item.css +6 -6
  138. package/styles/ui-tree.css +1 -1
  139. package/vanilla/UiActionBar.d.ts +1 -1
  140. package/vanilla/UiActionBar.js +5 -1
  141. package/vanilla/UiAffordanceScope.d.ts +1 -1
  142. package/vanilla/UiAffordanceScope.js +3 -2
  143. package/vanilla/UiAvatar.d.ts +1 -1
  144. package/vanilla/UiAvatar.js +4 -3
  145. package/vanilla/UiAvatarGroup.d.ts +1 -1
  146. package/vanilla/UiAvatarGroup.js +3 -2
  147. package/vanilla/UiBadge.d.ts +1 -1
  148. package/vanilla/UiBadge.js +2 -1
  149. package/vanilla/UiBreadcrumbItem.d.ts +1 -1
  150. package/vanilla/UiBreadcrumbItem.js +2 -1
  151. package/vanilla/UiBreadcrumbs.d.ts +1 -1
  152. package/vanilla/UiBreadcrumbs.js +4 -7
  153. package/vanilla/UiButton.d.ts +1 -1
  154. package/vanilla/UiButton.js +6 -4
  155. package/vanilla/UiCallout.d.ts +1 -1
  156. package/vanilla/UiCallout.js +3 -2
  157. package/vanilla/UiCard.d.ts +1 -1
  158. package/vanilla/UiCard.js +6 -2
  159. package/vanilla/UiCheckbox.d.ts +1 -1
  160. package/vanilla/UiCheckbox.js +4 -2
  161. package/vanilla/UiCluster.d.ts +1 -1
  162. package/vanilla/UiCluster.js +2 -1
  163. package/vanilla/UiCombobox.d.ts +3 -2
  164. package/vanilla/UiCombobox.js +8 -2
  165. package/vanilla/UiContainer.d.ts +1 -1
  166. package/vanilla/UiContainer.js +2 -1
  167. package/vanilla/UiContextMenu.d.ts +1 -1
  168. package/vanilla/UiContextMenu.js +3 -2
  169. package/vanilla/UiCover.d.ts +1 -1
  170. package/vanilla/UiCover.js +4 -5
  171. package/vanilla/UiDescriptionItem.d.ts +1 -1
  172. package/vanilla/UiDescriptionItem.js +4 -7
  173. package/vanilla/UiDescriptionList.d.ts +1 -1
  174. package/vanilla/UiDescriptionList.js +2 -1
  175. package/vanilla/UiDialog.d.ts +1 -1
  176. package/vanilla/UiDialog.js +4 -2
  177. package/vanilla/UiDisclosure.d.ts +1 -1
  178. package/vanilla/UiDisclosure.js +4 -2
  179. package/vanilla/UiEditable.d.ts +1 -1
  180. package/vanilla/UiEditable.js +2 -2
  181. package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
  182. package/vanilla/UiEditorInsertTableGrid.js +1 -1
  183. package/vanilla/UiEditorMentionMenu.d.ts +1 -1
  184. package/vanilla/UiEditorMentionMenu.js +5 -2
  185. package/vanilla/UiEditorMentionMenuItem.d.ts +1 -1
  186. package/vanilla/UiEditorMentionMenuItem.js +3 -1
  187. package/vanilla/UiEditorSlashMenu.d.ts +1 -1
  188. package/vanilla/UiEditorSlashMenu.js +6 -2
  189. package/vanilla/UiEditorSlashMenuGroup.d.ts +1 -1
  190. package/vanilla/UiEditorSlashMenuGroup.js +4 -7
  191. package/vanilla/UiEditorSlashMenuItem.d.ts +1 -1
  192. package/vanilla/UiEditorSlashMenuItem.js +2 -1
  193. package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
  194. package/vanilla/UiEditorTableContextMenu.js +2 -2
  195. package/vanilla/UiEditorTableOverlay.d.ts +12 -2
  196. package/vanilla/UiEditorTableOverlay.js +2 -2
  197. package/vanilla/UiEditorTableToolbar.d.ts +1 -1
  198. package/vanilla/UiEditorTableToolbar.js +2 -2
  199. package/vanilla/UiEditorToolbar.d.ts +1 -1
  200. package/vanilla/UiEditorToolbar.js +2 -1
  201. package/vanilla/UiFloatingActionButton.d.ts +1 -1
  202. package/vanilla/UiFloatingActionButton.js +2 -1
  203. package/vanilla/UiFormField.d.ts +1 -1
  204. package/vanilla/UiFormField.js +6 -1
  205. package/vanilla/UiGrid.d.ts +1 -1
  206. package/vanilla/UiGrid.js +4 -3
  207. package/vanilla/UiIcon.d.ts +1 -1
  208. package/vanilla/UiIcon.js +1 -1
  209. package/vanilla/UiIconButton.d.ts +1 -1
  210. package/vanilla/UiIconButton.js +4 -3
  211. package/vanilla/UiInput.d.ts +5 -4
  212. package/vanilla/UiInput.js +16 -13
  213. package/vanilla/UiInputGroup.d.ts +1 -1
  214. package/vanilla/UiInputGroup.js +5 -1
  215. package/vanilla/UiList.d.ts +1 -1
  216. package/vanilla/UiList.js +4 -2
  217. package/vanilla/UiListItem.d.ts +1 -1
  218. package/vanilla/UiListItem.js +5 -1
  219. package/vanilla/UiListbox.d.ts +1 -1
  220. package/vanilla/UiListbox.js +3 -2
  221. package/vanilla/UiMenu.d.ts +1 -1
  222. package/vanilla/UiMenu.js +3 -2
  223. package/vanilla/UiMenuGroup.d.ts +1 -1
  224. package/vanilla/UiMenuGroup.js +2 -1
  225. package/vanilla/UiMenuItem.d.ts +1 -1
  226. package/vanilla/UiMenuItem.js +6 -2
  227. package/vanilla/UiMeter.d.ts +1 -1
  228. package/vanilla/UiMeter.js +2 -2
  229. package/vanilla/UiNavItem.d.ts +2 -2
  230. package/vanilla/UiNavItem.js +11 -5
  231. package/vanilla/UiPageHeader.d.ts +1 -1
  232. package/vanilla/UiPageHeader.js +8 -5
  233. package/vanilla/UiPopover.d.ts +1 -1
  234. package/vanilla/UiPopover.js +3 -2
  235. package/vanilla/UiRadio.d.ts +1 -1
  236. package/vanilla/UiRadio.js +4 -2
  237. package/vanilla/UiRadioGroup.d.ts +1 -1
  238. package/vanilla/UiRadioGroup.js +3 -2
  239. package/vanilla/UiReel.d.ts +1 -1
  240. package/vanilla/UiReel.js +2 -1
  241. package/vanilla/UiScrollArea.d.ts +1 -1
  242. package/vanilla/UiScrollArea.js +3 -2
  243. package/vanilla/UiSearchResultRow.d.ts +1 -1
  244. package/vanilla/UiSearchResultRow.js +6 -1
  245. package/vanilla/UiSearchShell.d.ts +1 -1
  246. package/vanilla/UiSearchShell.js +6 -2
  247. package/vanilla/UiSection.d.ts +1 -1
  248. package/vanilla/UiSection.js +5 -2
  249. package/vanilla/UiSelect.d.ts +1 -1
  250. package/vanilla/UiSelect.js +3 -2
  251. package/vanilla/UiSeparator.d.ts +1 -1
  252. package/vanilla/UiSeparator.js +3 -7
  253. package/vanilla/UiSidebar.d.ts +1 -1
  254. package/vanilla/UiSidebar.js +3 -2
  255. package/vanilla/UiSpinner.d.ts +1 -1
  256. package/vanilla/UiSpinner.js +2 -2
  257. package/vanilla/UiStack.d.ts +1 -1
  258. package/vanilla/UiStack.js +2 -1
  259. package/vanilla/UiStatusMessage.d.ts +1 -1
  260. package/vanilla/UiStatusMessage.js +4 -2
  261. package/vanilla/UiSwitch.d.ts +1 -1
  262. package/vanilla/UiSwitch.js +4 -2
  263. package/vanilla/UiSwitcher.d.ts +1 -1
  264. package/vanilla/UiSwitcher.js +3 -2
  265. package/vanilla/UiTable.d.ts +1 -1
  266. package/vanilla/UiTable.js +3 -2
  267. package/vanilla/UiTabs.d.ts +1 -1
  268. package/vanilla/UiTabs.js +4 -2
  269. package/vanilla/UiText.d.ts +1 -1
  270. package/vanilla/UiText.js +13 -2
  271. package/vanilla/UiTextarea.d.ts +1 -1
  272. package/vanilla/UiTextarea.js +3 -3
  273. package/vanilla/UiToast.d.ts +1 -1
  274. package/vanilla/UiToast.js +4 -2
  275. package/vanilla/UiToastRegion.d.ts +1 -1
  276. package/vanilla/UiToastRegion.js +3 -2
  277. package/vanilla/UiTooltip.d.ts +1 -1
  278. package/vanilla/UiTooltip.js +3 -2
  279. package/vanilla/UiTopBar.d.ts +1 -1
  280. package/vanilla/UiTopBar.js +5 -1
  281. package/vanilla/UiTree.d.ts +1 -1
  282. package/vanilla/UiTree.js +3 -2
  283. package/vanilla/UiTreeItem.d.ts +1 -1
  284. package/vanilla/UiTreeItem.js +8 -4
  285. package/vue/UiActionBar.vue +33 -2
  286. package/vue/UiAffordanceScope.d.ts +23 -8
  287. package/vue/UiAffordanceScope.vue +90 -17
  288. package/vue/UiAvatar.d.ts +77 -19
  289. package/vue/UiAvatar.vue +151 -31
  290. package/vue/UiAvatarGroup.d.ts +50 -13
  291. package/vue/UiAvatarGroup.vue +121 -23
  292. package/vue/UiBadge.d.ts +32 -10
  293. package/vue/UiBadge.vue +104 -17
  294. package/vue/UiBreadcrumbItem.d.ts +14 -6
  295. package/vue/UiBreadcrumbItem.vue +82 -15
  296. package/vue/UiBreadcrumbs.d.ts +14 -6
  297. package/vue/UiBreadcrumbs.vue +78 -10
  298. package/vue/UiButton.d.ts +122 -27
  299. package/vue/UiButton.vue +288 -64
  300. package/vue/UiCallout.d.ts +14 -6
  301. package/vue/UiCallout.vue +84 -16
  302. package/vue/UiCard.d.ts +41 -12
  303. package/vue/UiCard.vue +149 -25
  304. package/vue/UiCheckbox.d.ts +85 -28
  305. package/vue/UiCheckbox.vue +173 -43
  306. package/vue/UiCluster.d.ts +41 -7
  307. package/vue/UiCluster.vue +122 -13
  308. package/vue/UiCombobox.d.ts +303 -110
  309. package/vue/UiCombobox.vue +723 -412
  310. package/vue/UiContainer.d.ts +23 -5
  311. package/vue/UiContainer.vue +89 -9
  312. package/vue/UiContextMenu.d.ts +38 -23
  313. package/vue/UiContextMenu.vue +113 -38
  314. package/vue/UiCover.d.ts +14 -6
  315. package/vue/UiCover.vue +76 -12
  316. package/vue/UiDescriptionItem.d.ts +14 -6
  317. package/vue/UiDescriptionItem.vue +78 -11
  318. package/vue/UiDescriptionList.d.ts +32 -9
  319. package/vue/UiDescriptionList.vue +106 -16
  320. package/vue/UiDialog.d.ts +89 -30
  321. package/vue/UiDialog.vue +168 -38
  322. package/vue/UiDisclosure.d.ts +70 -27
  323. package/vue/UiDisclosure.vue +149 -36
  324. package/vue/UiEditable.d.ts +119 -41
  325. package/vue/UiEditable.vue +220 -62
  326. package/vue/UiEditorInsertTableGrid.d.ts +46 -17
  327. package/vue/UiEditorInsertTableGrid.vue +215 -40
  328. package/vue/UiEditorMentionMenu.d.ts +128 -41
  329. package/vue/UiEditorMentionMenu.vue +211 -37
  330. package/vue/UiEditorMentionMenuItem.d.ts +32 -10
  331. package/vue/UiEditorMentionMenuItem.vue +98 -17
  332. package/vue/UiEditorSlashMenu.d.ts +110 -37
  333. package/vue/UiEditorSlashMenu.vue +189 -31
  334. package/vue/UiEditorSlashMenuGroup.d.ts +14 -6
  335. package/vue/UiEditorSlashMenuGroup.vue +80 -12
  336. package/vue/UiEditorSlashMenuItem.d.ts +50 -14
  337. package/vue/UiEditorSlashMenuItem.vue +120 -23
  338. package/vue/UiEditorTableContextMenu.d.ts +64 -20
  339. package/vue/UiEditorTableContextMenu.vue +326 -91
  340. package/vue/UiEditorTableOverlay.d.ts +170 -44
  341. package/vue/UiEditorTableOverlay.vue +420 -149
  342. package/vue/UiEditorTableToolbar.d.ts +64 -20
  343. package/vue/UiEditorTableToolbar.vue +344 -107
  344. package/vue/UiEditorToolbar.d.ts +14 -6
  345. package/vue/UiEditorToolbar.vue +79 -15
  346. package/vue/UiFloatingActionButton.d.ts +32 -10
  347. package/vue/UiFloatingActionButton.vue +96 -18
  348. package/vue/UiFormField.d.ts +32 -10
  349. package/vue/UiFormField.vue +99 -19
  350. package/vue/UiGrid.d.ts +32 -6
  351. package/vue/UiGrid.vue +95 -11
  352. package/vue/UiIcon.d.ts +14 -6
  353. package/vue/UiIcon.vue +99 -14
  354. package/vue/UiIconButton.d.ts +77 -19
  355. package/vue/UiIconButton.vue +176 -39
  356. package/vue/UiInput.d.ts +50 -19
  357. package/vue/UiInput.vue +326 -33
  358. package/vue/UiInputGroup.d.ts +14 -6
  359. package/vue/UiInputGroup.vue +79 -15
  360. package/vue/UiList.d.ts +41 -12
  361. package/vue/UiList.vue +125 -22
  362. package/vue/UiListItem.d.ts +23 -8
  363. package/vue/UiListItem.vue +88 -16
  364. package/vue/UiListbox.d.ts +86 -27
  365. package/vue/UiListbox.vue +272 -64
  366. package/vue/UiMenu.d.ts +69 -33
  367. package/vue/UiMenu.vue +142 -38
  368. package/vue/UiMenuGroup.d.ts +14 -6
  369. package/vue/UiMenuGroup.vue +80 -11
  370. package/vue/UiMenuItem.d.ts +61 -25
  371. package/vue/UiMenuItem.vue +174 -45
  372. package/vue/UiMeter.d.ts +68 -18
  373. package/vue/UiMeter.vue +215 -41
  374. package/vue/UiNavItem.d.ts +50 -11
  375. package/vue/UiNavItem.vue +163 -29
  376. package/vue/UiPageHeader.d.ts +14 -6
  377. package/vue/UiPageHeader.vue +75 -12
  378. package/vue/UiPopover.d.ts +43 -21
  379. package/vue/UiPopover.vue +147 -27
  380. package/vue/UiRadio.d.ts +67 -24
  381. package/vue/UiRadio.vue +147 -36
  382. package/vue/UiRadioGroup.d.ts +79 -29
  383. package/vue/UiRadioGroup.vue +162 -41
  384. package/vue/UiReel.d.ts +32 -6
  385. package/vue/UiReel.vue +97 -11
  386. package/vue/UiScrollArea.d.ts +14 -6
  387. package/vue/UiScrollArea.vue +83 -14
  388. package/vue/UiSearchResultRow.d.ts +23 -8
  389. package/vue/UiSearchResultRow.vue +86 -16
  390. package/vue/UiSearchShell.d.ts +48 -19
  391. package/vue/UiSearchShell.vue +120 -26
  392. package/vue/UiSection.d.ts +32 -10
  393. package/vue/UiSection.vue +103 -17
  394. package/vue/UiSelect.d.ts +59 -17
  395. package/vue/UiSelect.vue +140 -29
  396. package/vue/UiSeparator.d.ts +14 -6
  397. package/vue/UiSeparator.vue +80 -9
  398. package/vue/UiSidebar.d.ts +95 -31
  399. package/vue/UiSidebar.vue +172 -39
  400. package/vue/UiSpinner.d.ts +23 -8
  401. package/vue/UiSpinner.vue +115 -24
  402. package/vue/UiStack.d.ts +32 -6
  403. package/vue/UiStack.vue +107 -11
  404. package/vue/UiStatusMessage.d.ts +32 -10
  405. package/vue/UiStatusMessage.vue +109 -19
  406. package/vue/UiSwitch.d.ts +67 -24
  407. package/vue/UiSwitch.vue +147 -36
  408. package/vue/UiSwitcher.d.ts +41 -7
  409. package/vue/UiSwitcher.vue +118 -15
  410. package/vue/UiTable.d.ts +23 -8
  411. package/vue/UiTable.vue +91 -17
  412. package/vue/UiTabs.d.ts +66 -23
  413. package/vue/UiTabs.vue +230 -44
  414. package/vue/UiText.d.ts +68 -18
  415. package/vue/UiText.vue +308 -48
  416. package/vue/UiTextarea.d.ts +84 -21
  417. package/vue/UiTextarea.vue +172 -38
  418. package/vue/UiToast.d.ts +28 -13
  419. package/vue/UiToast.vue +103 -24
  420. package/vue/UiToastRegion.d.ts +29 -14
  421. package/vue/UiToastRegion.vue +202 -47
  422. package/vue/UiTooltip.d.ts +81 -31
  423. package/vue/UiTooltip.vue +192 -37
  424. package/vue/UiTopBar.vue +33 -2
  425. package/vue/UiTree.d.ts +72 -29
  426. package/vue/UiTree.vue +170 -49
  427. package/vue/UiTreeItem.d.ts +136 -35
  428. package/vue/UiTreeItem.vue +232 -66
  429. package/vue/chunks/UiActionBar.js +16 -3
  430. package/vue/chunks/UiAffordanceScope.js +66 -11
  431. package/vue/chunks/UiAvatar.js +121 -20
  432. package/vue/chunks/UiAvatarGroup.js +94 -15
  433. package/vue/chunks/UiBadge.js +82 -10
  434. package/vue/chunks/UiBreadcrumbItem.js +43 -9
  435. package/vue/chunks/UiBreadcrumbs.js +41 -5
  436. package/vue/chunks/UiButton.js +237 -51
  437. package/vue/chunks/UiCallout.js +53 -11
  438. package/vue/chunks/UiCard.js +145 -18
  439. package/vue/chunks/UiCheckbox.js +130 -30
  440. package/vue/chunks/UiCluster.js +99 -12
  441. package/vue/chunks/UiCombobox.js +545 -162
  442. package/vue/chunks/UiContainer.js +65 -7
  443. package/vue/chunks/UiContextMenu.js +56 -11
  444. package/vue/chunks/UiCover.js +41 -6
  445. package/vue/chunks/UiDescriptionItem.js +39 -4
  446. package/vue/chunks/UiDescriptionList.js +80 -10
  447. package/vue/chunks/UiDialog.js +125 -18
  448. package/vue/chunks/UiDisclosure.js +102 -17
  449. package/vue/chunks/UiEditable.js +154 -29
  450. package/vue/chunks/UiEditorInsertTableGrid.js +154 -31
  451. package/vue/chunks/UiEditorMentionMenu.js +221 -18
  452. package/vue/chunks/UiEditorMentionMenuItem.js +64 -7
  453. package/vue/chunks/UiEditorSlashMenu.js +201 -14
  454. package/vue/chunks/UiEditorSlashMenuGroup.js +43 -9
  455. package/vue/chunks/UiEditorSlashMenuItem.js +80 -14
  456. package/vue/chunks/UiEditorTableContextMenu.js +220 -49
  457. package/vue/chunks/UiEditorTableOverlay.js +390 -85
  458. package/vue/chunks/UiEditorTableToolbar.js +248 -71
  459. package/vue/chunks/UiEditorToolbar.js +44 -10
  460. package/vue/chunks/UiFloatingActionButton.js +57 -9
  461. package/vue/chunks/UiFormField.js +63 -12
  462. package/vue/chunks/UiGrid.js +80 -9
  463. package/vue/chunks/UiIcon.js +73 -16
  464. package/vue/chunks/UiIconButton.js +126 -28
  465. package/vue/chunks/UiInput.js +328 -22
  466. package/vue/chunks/UiInputGroup.js +44 -10
  467. package/vue/chunks/UiList.js +104 -15
  468. package/vue/chunks/UiListItem.js +57 -8
  469. package/vue/chunks/UiListbox.js +208 -49
  470. package/vue/chunks/UiMenu.js +88 -15
  471. package/vue/chunks/UiMenuGroup.js +41 -5
  472. package/vue/chunks/UiMenuItem.js +111 -32
  473. package/vue/chunks/UiMeter.js +166 -36
  474. package/vue/chunks/UiNavItem.js +133 -37
  475. package/vue/chunks/UiPageHeader.js +41 -6
  476. package/vue/chunks/UiPopover.js +81 -11
  477. package/vue/chunks/UiRadio.js +115 -24
  478. package/vue/chunks/UiRadioGroup.js +108 -19
  479. package/vue/chunks/UiReel.js +81 -10
  480. package/vue/chunks/UiScrollArea.js +47 -10
  481. package/vue/chunks/UiSearchResultRow.js +47 -8
  482. package/vue/chunks/UiSearchShell.js +84 -24
  483. package/vue/chunks/UiSection.js +77 -10
  484. package/vue/chunks/UiSelect.js +108 -20
  485. package/vue/chunks/UiSeparator.js +41 -5
  486. package/vue/chunks/UiSidebar.js +136 -20
  487. package/vue/chunks/UiSpinner.js +64 -19
  488. package/vue/chunks/UiStack.js +87 -10
  489. package/vue/chunks/UiStatusMessage.js +82 -12
  490. package/vue/chunks/UiSwitch.js +115 -24
  491. package/vue/chunks/UiSwitcher.js +103 -15
  492. package/vue/chunks/UiTable.js +63 -11
  493. package/vue/chunks/UiTabs.js +170 -30
  494. package/vue/chunks/UiText.js +365 -38
  495. package/vue/chunks/UiTextarea.js +132 -26
  496. package/vue/chunks/UiToast.js +70 -12
  497. package/vue/chunks/UiToastRegion.js +154 -33
  498. package/vue/chunks/UiTooltip.js +124 -16
  499. package/vue/chunks/UiTopBar.js +16 -3
  500. package/vue/chunks/UiTree.js +107 -15
  501. package/vue/chunks/UiTreeItem.js +167 -43
  502. package/vue/chunks/control.js +171 -0
  503. package/vue/chunks/host.js +170 -27
  504. package/vue/chunks/props.js +477 -0
  505. package/vue/components.css +1197 -1197
  506. package/vue/editor/index.js +58 -15
  507. package/vue/editor/primitives.d.ts +52 -2
  508. package/vue/host.ts +370 -39
@@ -1659,7 +1659,7 @@ var LoomaEditor = defineComponent({
1659
1659
  headerRow: tableUi.headerRow,
1660
1660
  headerColumn: tableUi.headerColumn,
1661
1661
  actions: tableActions,
1662
- onAction: runTableAction
1662
+ onAction: (event) => runTableAction(event.detail)
1663
1663
  };
1664
1664
  return h("div", {
1665
1665
  ...attrs,
@@ -1742,7 +1742,7 @@ var LoomaEditor = defineComponent({
1742
1742
  disclosure: true,
1743
1743
  filter: "label",
1744
1744
  value: codeUi.language,
1745
- onValueChange: chooseCodeLanguage
1745
+ onValueChange: (event) => chooseCodeLanguage(event.detail)
1746
1746
  }, () => codeLanguageOptions.value.map((option) => h("option", { value: option.value }, option.label)))]) : null,
1747
1747
  instance && props.editable && mobile.value && editorFocused.value ? h("div", {
1748
1748
  ref: mobileToolbarShell,
@@ -1850,7 +1850,7 @@ var LoomaEditor = defineComponent({
1850
1850
  for: blockActionAnchorId,
1851
1851
  placement: mobile.value ? "top-start" : "bottom-start",
1852
1852
  onOpen: captureBlockAction,
1853
- onSelect: ({ value }) => runBlockAction(value)
1853
+ onSelect: (event) => runBlockAction(event.detail.value)
1854
1854
  }, () => [
1855
1855
  h(MenuItem, { value: "insert-below" }, () => "Insert paragraph below"),
1856
1856
  h(MenuItem, { value: "duplicate" }, () => "Duplicate block"),
@@ -1869,8 +1869,8 @@ var LoomaEditor = defineComponent({
1869
1869
  }
1870
1870
  }, () => [h(EditorInsertTableGrid, {
1871
1871
  open: true,
1872
- onInsert: (detail) => {
1873
- instance?.chain().focus().insertTable(detail).run();
1872
+ onInsert: (event) => {
1873
+ instance?.chain().focus().insertTable(event.detail).run();
1874
1874
  tablePickerOpen.value = false;
1875
1875
  }
1876
1876
  })]),
@@ -1880,11 +1880,11 @@ var LoomaEditor = defineComponent({
1880
1880
  items: managedSlashMenuItems(slash.items),
1881
1881
  selectedIndex: slash.selectedIndex,
1882
1882
  anchorRect: managedMenuAnchorRect(slash.rect),
1883
- onHighlight: ({ index }) => {
1884
- slash.selectedIndex = index;
1883
+ onHighlight: (event) => {
1884
+ slash.selectedIndex = event.detail.index;
1885
1885
  },
1886
- onSelect: ({ index }) => {
1887
- slash.select?.(index);
1886
+ onSelect: (event) => {
1887
+ slash.select?.(event.detail.index);
1888
1888
  }
1889
1889
  }) : null,
1890
1890
  mention.active && (mention.loading || mention.items.length > 0) ? h(EditorMentionMenu, {
@@ -1895,12 +1895,12 @@ var LoomaEditor = defineComponent({
1895
1895
  selectedIndex: mention.selectedIndex,
1896
1896
  anchorRect: managedMenuAnchorRect(mention.rect),
1897
1897
  loading: mention.loading,
1898
- onHighlight: ({ index }) => {
1899
- mention.selectedIndex = index;
1900
- mention.highlight?.(index);
1898
+ onHighlight: (event) => {
1899
+ mention.selectedIndex = event.detail.index;
1900
+ mention.highlight?.(event.detail.index);
1901
1901
  },
1902
- onSelect: ({ index }) => {
1903
- mention.select?.(index);
1902
+ onSelect: (event) => {
1903
+ mention.select?.(event.detail.index);
1904
1904
  }
1905
1905
  }) : null,
1906
1906
  tableUi.toolbarOpen ? h("div", {
@@ -1917,7 +1917,50 @@ var LoomaEditor = defineComponent({
1917
1917
  }, [h(EditorTableOverlay, {
1918
1918
  open: true,
1919
1919
  geometry: tableUi.geometry,
1920
- onAction: runOverlayAction
1920
+ onAddRowBefore: (event) => runOverlayAction({
1921
+ action: "add-row-before",
1922
+ boundaryIndex: event.detail.boundaryIndex
1923
+ }),
1924
+ onAddRowAfter: (event) => runOverlayAction({
1925
+ action: "add-row-after",
1926
+ boundaryIndex: event.detail.boundaryIndex
1927
+ }),
1928
+ onAddColumnBefore: (event) => runOverlayAction({
1929
+ action: "add-column-before",
1930
+ boundaryIndex: event.detail.boundaryIndex
1931
+ }),
1932
+ onAddColumnAfter: (event) => runOverlayAction({
1933
+ action: "add-column-after",
1934
+ boundaryIndex: event.detail.boundaryIndex
1935
+ }),
1936
+ onSelectRow: (event) => runOverlayAction({
1937
+ action: "select-row",
1938
+ ...event.detail
1939
+ }),
1940
+ onSelectColumn: (event) => runOverlayAction({
1941
+ action: "select-column",
1942
+ ...event.detail
1943
+ }),
1944
+ onReorderRow: (event) => runOverlayAction({
1945
+ action: "reorder-row",
1946
+ ...event.detail
1947
+ }),
1948
+ onReorderColumn: (event) => runOverlayAction({
1949
+ action: "reorder-column",
1950
+ ...event.detail
1951
+ }),
1952
+ onOpenCellMenu: (event) => runOverlayAction({
1953
+ action: "open-cell-menu",
1954
+ ...event.detail
1955
+ }),
1956
+ onOpenRowMenu: (event) => runOverlayAction({
1957
+ action: "open-row-menu",
1958
+ ...event.detail
1959
+ }),
1960
+ onOpenColumnMenu: (event) => runOverlayAction({
1961
+ action: "open-column-menu",
1962
+ ...event.detail
1963
+ })
1921
1964
  })]) : null,
1922
1965
  tableUi.menuOpen ? h("div", {
1923
1966
  ref: tableMenuShell,
@@ -2,14 +2,64 @@
2
2
  * The editor components, as Vue components. They are the converted components from
3
3
  * `@threadlabs/looma/vue`, re-exported beside the editor that composes them.
4
4
  */
5
- import type { InsertTableEventDetail, MentionMenuHighlightEventDetail, MentionMenuSelectEventDetail, SlashMenuHighlightEventDetail, SlashMenuSelectEventDetail, TableContextMenuActionEventDetail, TableOverlayActionEventDetail } from "@threadlabs/looma/editor";
5
+ import type { InsertTableEventDetail, MentionMenuHighlightEventDetail, MentionMenuSelectEventDetail, SlashMenuHighlightEventDetail, SlashMenuSelectEventDetail, TableContextMenuActionEventDetail } from "@threadlabs/looma/editor";
6
6
  export { EditorInsertTableGrid, EditorMentionMenu, EditorSlashMenu, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, } from "@threadlabs/looma/vue";
7
7
  /** The editor components' event details, by event name. */
8
8
  export interface VueEditorAdapterEventMap {
9
9
  highlight: MentionMenuHighlightEventDetail | SlashMenuHighlightEventDetail;
10
10
  select: MentionMenuSelectEventDetail | SlashMenuSelectEventDetail;
11
- action: TableContextMenuActionEventDetail | TableOverlayActionEventDetail;
11
+ action: TableContextMenuActionEventDetail;
12
12
  insert: InsertTableEventDetail;
13
+ "add-row-before": {
14
+ boundaryIndex: number;
15
+ };
16
+ "add-row-after": {
17
+ boundaryIndex: number;
18
+ };
19
+ "add-column-before": {
20
+ boundaryIndex: number;
21
+ };
22
+ "add-column-after": {
23
+ boundaryIndex: number;
24
+ };
25
+ "select-row": {
26
+ rowIndex: number;
27
+ columnIndex: number;
28
+ };
29
+ "select-column": {
30
+ rowIndex: number;
31
+ columnIndex: number;
32
+ };
33
+ "open-cell-menu": {
34
+ rowIndex: number;
35
+ columnIndex: number;
36
+ anchor: {
37
+ left: number;
38
+ top: number;
39
+ right: number;
40
+ bottom: number;
41
+ };
42
+ };
43
+ "open-row-menu": {
44
+ rowIndex: number;
45
+ columnIndex: number;
46
+ anchor: {
47
+ left: number;
48
+ top: number;
49
+ right: number;
50
+ bottom: number;
51
+ };
52
+ };
53
+ "open-column-menu": {
54
+ rowIndex: number;
55
+ columnIndex: number;
56
+ anchor: {
57
+ left: number;
58
+ top: number;
59
+ right: number;
60
+ bottom: number;
61
+ };
62
+ };
13
63
  }
14
64
  /** Each Vue editor component's element tag, for tooling that enumerates them. */
15
65
  export declare const EDITOR_ADAPTER_COMPONENT_TAG_MAP: {
package/vue/host.ts CHANGED
@@ -1,47 +1,287 @@
1
- // Generated by HTML Next 1.0.0-alpha.7 for Vue 3.5. Do not edit.
2
- import { computed, onBeforeUnmount, onMounted, shallowRef, watchEffect } from 'vue'
1
+ // Generated by HTML Next 1.0.0-alpha.11 for Vue 3.5. Do not edit.
2
+ import {
3
+ computed,
4
+ Fragment,
5
+ getCurrentInstance,
6
+ onBeforeUnmount,
7
+ onBeforeUpdate,
8
+ onMounted,
9
+ onUpdated,
10
+ shallowRef,
11
+ useSlots,
12
+ watchEffect,
13
+ } from 'vue'
14
+
15
+ interface DataReadOptions {
16
+ readonly source: string
17
+ readonly definition: string
18
+ readonly type?: string
19
+ readonly debounce?: number
20
+ readonly poll?: number
21
+ readonly parameters: () => Readonly<Record<string, unknown>>
22
+ }
23
+
24
+ function dataURL(
25
+ source: string,
26
+ baseURL: string,
27
+ parameters: Readonly<Record<string, unknown>>,
28
+ ): string {
29
+ const used = new Set<string>()
30
+ const expanded = source.replace(/\{([A-Za-z_$][A-Za-z0-9_$-]*)\}/g, (_match, name: string) => {
31
+ used.add(name)
32
+ const value = parameters[name]
33
+ return value == null ? '' : encodeURIComponent(String(value))
34
+ })
35
+ const url = new URL(expanded, baseURL)
36
+ for (const [name, value] of Object.entries(parameters)) {
37
+ if (used.has(name) || value == null) continue
38
+ if (Array.isArray(value)) {
39
+ for (const item of value) url.searchParams.append(name, String(item))
40
+ } else url.searchParams.set(name, String(value))
41
+ }
42
+ return url.href
43
+ }
44
+
45
+ /** A Vue-owned declared read; no request is made during SSR. */
46
+ export function useDataRead(state: { value: any }, options: DataReadOptions): void {
47
+ let value: unknown = null
48
+ let parameters: Readonly<Record<string, unknown>> = {}
49
+ let abort: AbortController | undefined
50
+ let timer: ReturnType<typeof setTimeout> | undefined
51
+ let generation = 0
52
+ let connected = false
53
+ let stop: (() => void) | undefined
54
+ const cancel = (): void => {
55
+ abort?.abort()
56
+ abort = undefined
57
+ if (timer !== undefined) clearTimeout(timer)
58
+ timer = undefined
59
+ }
60
+ const stale = (current: number): boolean => !connected || current !== generation
61
+ const request = async (current: number): Promise<void> => {
62
+ if (stale(current)) return
63
+ const controller = new AbortController()
64
+ abort = controller
65
+ state.value = { pending: true, value, error: null, ok: false }
66
+ try {
67
+ const definition = (() => {
68
+ try {
69
+ return new URL(options.definition, document.baseURI).href
70
+ } catch {
71
+ return document.baseURI
72
+ }
73
+ })()
74
+ const response = await fetch(dataURL(options.source, definition, parameters), {
75
+ signal: controller.signal,
76
+ })
77
+ if (!response.ok) throw new TypeError(`Request failed with ${response.status}.`)
78
+ const next = options.type === 'text' || options.type === 'string'
79
+ ? await response.text()
80
+ : await response.json()
81
+ if (stale(current)) return
82
+ value = next
83
+ state.value = { pending: false, value, error: null, ok: true }
84
+ } catch (error) {
85
+ if (controller.signal.aborted || stale(current)) return
86
+ state.value = { pending: false, value, error, ok: false }
87
+ } finally {
88
+ if (abort === controller) abort = undefined
89
+ if (!stale(current) && (options.poll ?? 0) > 0) {
90
+ timer = setTimeout(() => {
91
+ void request(current)
92
+ }, options.poll)
93
+ }
94
+ }
95
+ }
96
+ const update = (next: Readonly<Record<string, unknown>>): void => {
97
+ parameters = { ...next }
98
+ connected = true
99
+ cancel()
100
+ const current = ++generation
101
+ if ((options.debounce ?? 0) > 0) {
102
+ timer = setTimeout(() => {
103
+ void request(current)
104
+ }, options.debounce)
105
+ } else void request(current)
106
+ }
107
+ onMounted(() => {
108
+ stop = watchEffect(() => update(options.parameters()))
109
+ })
110
+ onBeforeUnmount(() => {
111
+ stop?.()
112
+ connected = false
113
+ generation += 1
114
+ cancel()
115
+ })
116
+ }
3
117
 
4
118
  /** A reactive value the host reads: Vue's ref, shallowRef, computed, and useTemplateRef all match. */
5
119
  export interface Readable<T> {
6
120
  readonly value: T
7
121
  }
8
122
 
123
+ interface ConnectionHub {
124
+ readonly observer: MutationObserver
125
+ readonly checks: Set<() => void>
126
+ }
127
+
128
+ const connectionHubs = new WeakMap<Document, ConnectionHub>()
129
+
130
+ /** One native observer per document tracks externally detached controller roots. */
131
+ function observeConnection(element: Element, check: () => void): () => void {
132
+ const document = element.ownerDocument
133
+ let hub = connectionHubs.get(document)
134
+ if (hub === undefined) {
135
+ const Observer = document.defaultView?.MutationObserver
136
+ if (Observer === undefined) {
137
+ throw new TypeError('Controller connection tracking requires MutationObserver.')
138
+ }
139
+ const checks = new Set<() => void>()
140
+ const observer = new Observer(() => {
141
+ for (const current of checks) current()
142
+ })
143
+ observer.observe(document, { childList: true, subtree: true })
144
+ hub = { observer, checks }
145
+ connectionHubs.set(document, hub)
146
+ }
147
+ hub.checks.add(check)
148
+ return () => {
149
+ hub.checks.delete(check)
150
+ if (hub.checks.size === 0) {
151
+ hub.observer.disconnect()
152
+ connectionHubs.delete(document)
153
+ }
154
+ }
155
+ }
156
+
157
+ /** Keep native focus on the corresponding control when a root-level $match replaces its element. */
158
+ export function preserveRootFocus(root: Readable<Element | null>): void {
159
+ const focusable =
160
+ 'a[href], button, input, select, textarea, summary, [tabindex], [contenteditable]'
161
+ let previous: Element | null = null
162
+ let active: Element | null = null
163
+ let focusIndex = -1
164
+ onBeforeUpdate(() => {
165
+ previous = root.value
166
+ active = previous?.ownerDocument.activeElement ?? null
167
+ focusIndex =
168
+ previous !== null && active !== null && active !== previous && previous.contains(active)
169
+ ? Array.from(previous.querySelectorAll(focusable)).indexOf(active)
170
+ : -1
171
+ })
172
+ onUpdated(() => {
173
+ const next = root.value
174
+ if (previous === null || next === null || previous === next) return
175
+ const target = active === previous
176
+ ? next
177
+ : active?.isConnected === true && next.contains(active)
178
+ ? active
179
+ : focusIndex >= 0
180
+ ? next.querySelectorAll(focusable)[focusIndex]
181
+ : undefined
182
+ ;(target as HTMLElement | undefined)?.focus?.({ preventScroll: true })
183
+ })
184
+ }
185
+
9
186
  export interface ComponentHostOptions {
10
187
  /** The component's root element. */
11
188
  readonly root: Readable<HTMLElement | null>
12
189
  /** Dispatches a declared component event. */
13
190
  readonly dispatch: (name: string, detail?: unknown) => boolean
191
+ /** The authored controller edge, retained for the live loader's module diagnostic. */
192
+ readonly controllerSource?: { readonly specifier: string; readonly definition: string }
14
193
  /** The component's props, which a controller reads through `host.state`. */
15
- readonly props?: Readonly<Record<string, unknown>>
16
- /** Template refs, by the ref name the component declared. */
17
- readonly refs?: Readonly<Record<string, Readable<HTMLElement | null>>>
194
+ readonly props?: Readable<Readonly<Record<string, unknown>>>
195
+ /** Template refs, by the ref name the component declared. Vue collects a `v-for` ref into an array. */
196
+ readonly refs?: Readonly<Record<string, Readable<HTMLElement | HTMLElement[] | null>>>
18
197
  /** Declared state, which a controller reads and writes. */
19
198
  readonly state?: Readonly<Record<string, { value: any }>>
20
199
  /** Declared computed values, which a controller reads. */
21
200
  readonly computed?: Readonly<Record<string, Readable<unknown>>>
22
201
  }
23
202
 
203
+ /** Vue does not promise a `v-for` ref array in source order, and the host does. */
204
+ function inDocumentOrder(elements: readonly Element[]): Element[] {
205
+ return [...elements].sort((a, b) => (a.compareDocumentPosition(b) & 4) !== 0 ? -1 : 1)
206
+ }
207
+
208
+ /** Slot content flattened to the elements Vue mounted for it, descending through fragments. */
209
+ function slottedElements(nodes: readonly any[]): Element[] {
210
+ const elements: Element[] = []
211
+ for (const node of nodes) {
212
+ if (node.type === Fragment && Array.isArray(node.children)) {
213
+ elements.push(...slottedElements(node.children))
214
+ } else if (node.el instanceof Element) elements.push(node.el)
215
+ }
216
+ return elements
217
+ }
218
+
24
219
  /**
25
220
  * The controller host, built from Vue refs, effects, and lifecycle. Reads and writes reach the
26
- * component's own refs, so a controller's change renders as any other Vue change does, and the
27
- * effects and listeners it opens close when the component unmounts.
221
+ * component's own refs, so a controller's change renders as any other Vue change does. Vue
222
+ * hooks cover mount/unmount; a shared native observer also detects external root detachment
223
+ * and reinsertion without treating an in-tree move as a new connection.
28
224
  */
29
225
  export function useComponentHost(
30
- controller: ((host: never) => unknown) | undefined,
226
+ controllerLoader: () => Promise<unknown>,
31
227
  options: ComponentHostOptions,
32
228
  ) {
33
229
  const { root, dispatch, props, refs = {}, state = {}, computed: computedValues = {} } = options
230
+ const vueSlots = useSlots()
231
+ const component = getCurrentInstance()
232
+ const report = (error: unknown): void => {
233
+ const handler = component?.appContext.config.errorHandler
234
+ if (handler === undefined) {
235
+ queueMicrotask(() => {
236
+ throw error
237
+ })
238
+ } else handler(error, component?.proxy ?? null, 'HTML Next controller')
239
+ }
240
+ const controllerDiagnostic = (code: 'HJ001' | 'HJ002', reason?: unknown): Error => {
241
+ const edge = options.controllerSource
242
+ const source = edge?.definition ? new URL(edge.definition, document.baseURI).href : undefined
243
+ const url = new URL(edge?.specifier ?? '', source ?? document.baseURI).href
244
+ const tick = String.fromCharCode(96)
245
+ const message = code === 'HJ002'
246
+ ? 'Controller module ' + tick + url + tick + ' must default-export a function.'
247
+ : 'Controller module ' + tick + url + tick + ' failed to load: '
248
+ + (reason instanceof Error ? reason.message : String(reason)) + '.'
249
+ return Object.assign(
250
+ new Error((source === undefined ? '' : source + ': ') + code + ': ' + message),
251
+ {
252
+ name: 'HtmlDiagnosticError',
253
+ diagnostic: Object.freeze({ code, message, ...(source === undefined ? {} : { source }) }),
254
+ },
255
+ )
256
+ }
257
+ type ControllerModule = Record<string, unknown> & { readonly default: (host: unknown) => unknown }
258
+ let controllerModule: Promise<ControllerModule> | undefined
259
+ const loadControllerModule = (): Promise<ControllerModule> =>
260
+ controllerModule ??= Promise.resolve()
261
+ .then(controllerLoader)
262
+ .then((candidate) => {
263
+ const loaded = candidate as { readonly default?: unknown } | null
264
+ if (typeof loaded?.default !== 'function') throw controllerDiagnostic('HJ002')
265
+ return candidate as ControllerModule
266
+ })
267
+ .catch((error: unknown) => {
268
+ if (error instanceof Error && 'diagnostic' in error) throw error
269
+ throw controllerDiagnostic('HJ001', error)
270
+ })
34
271
  const stops: Array<() => void> = []
35
272
  const read = (name: string): unknown =>
36
273
  Object.hasOwn(state, name)
37
274
  ? state[name]!.value
38
275
  : Object.hasOwn(computedValues, name)
39
276
  ? computedValues[name]!.value
40
- : props?.[name]
277
+ : props?.value[name]
41
278
  const host = {
42
279
  get element(): Element {
43
280
  return root.value as Element
44
281
  },
282
+ get root(): Element {
283
+ return root.value as Element
284
+ },
45
285
  state: new Proxy({} as Record<string, unknown>, {
46
286
  get: (_target, name) => typeof name === 'string' ? read(name) : undefined,
47
287
  set: (_target, name, value) => {
@@ -55,20 +295,19 @@ export function useComponentHost(
55
295
  refs: Object.defineProperties(
56
296
  {},
57
297
  Object.fromEntries(
58
- Object.entries(refs).map((
59
- [name, ref],
60
- ) => [name, { enumerable: true, get: () => ref.value as Element }]),
298
+ Object.entries(refs).map(([name, ref]) => [name, {
299
+ enumerable: true,
300
+ get: () => Array.isArray(ref.value) ? inDocumentOrder(ref.value) : (ref.value as Element),
301
+ }]),
61
302
  ),
62
- ) as Readonly<Record<string, Element>>,
63
- elements: new Proxy({} as Record<string, Element | RadioNodeList | undefined>, {
303
+ ) as Readonly<Record<string, Element | readonly Element[]>>,
304
+ slots: new Proxy({} as Record<string, readonly Element[]>, {
64
305
  get: (_target, name) => {
65
- if (typeof name !== 'string' || root.value === null) return undefined
66
- const form = root.value instanceof HTMLFormElement
67
- ? root.value
68
- : root.value.querySelector('form')
69
- return form?.elements.namedItem(name)
70
- ?? root.value.querySelector(`[name="${CSS.escape(name)}"]`) ?? undefined
306
+ if (typeof name !== 'string') return undefined
307
+ const render = vueSlots[name]
308
+ return render === undefined ? [] : slottedElements(render())
71
309
  },
310
+ has: (_target, name) => typeof name === 'string' && vueSlots[name] !== undefined,
72
311
  }),
73
312
  signal<T>(initialValue: T) {
74
313
  // shallowRef holds the controller's own value and notifies only when it changes.
@@ -95,29 +334,62 @@ export function useComponentHost(
95
334
  stops.push(stop)
96
335
  return stop
97
336
  },
98
- on(event: string, listener: EventListener): () => void {
99
- const element = root.value
100
- element?.addEventListener(event, listener)
101
- const off = (): void => element?.removeEventListener(event, listener)
102
- stops.push(off)
103
- return off
104
- },
105
337
  dispatch,
106
338
  }
107
339
 
108
340
  let cleanup: void | (() => void)
109
- let started: Promise<void> | undefined
341
+ let started: Promise<ControllerModule> | undefined
342
+ let stopObserving: (() => void) | undefined
343
+ let connection = 0
344
+ let connected = false
345
+ let unmounted = false
346
+ const disconnect = (): void => {
347
+ if (!connected) return
348
+ connected = false
349
+ connection += 1
350
+ for (const stop of stops.splice(0)) stop()
351
+ cleanup?.()
352
+ cleanup = undefined
353
+ }
354
+ const synchronize = (): void => {
355
+ if (unmounted) return
356
+ if (root.value?.isConnected !== true) {
357
+ disconnect()
358
+ return
359
+ }
360
+ if (connected) return
361
+ connected = true
362
+ const current = ++connection
363
+ started = loadControllerModule().then(async (loaded) => {
364
+ if (!connected || current !== connection) return loaded
365
+ const result = await loaded.default(host as never)
366
+ if (typeof result === 'function') {
367
+ if (!connected || current !== connection) result()
368
+ else cleanup = result as () => void
369
+ }
370
+ return loaded
371
+ })
372
+ void started.catch(report)
373
+ }
110
374
  onMounted(() => {
111
- started = Promise.resolve(controller?.(host as never)).then((result) => {
112
- if (typeof result === 'function') cleanup = result as () => void
375
+ if (root.value === null) return
376
+ stopObserving = observeConnection(root.value, () => {
377
+ try {
378
+ synchronize()
379
+ } catch (error) {
380
+ report(error)
381
+ }
113
382
  })
383
+ synchronize()
114
384
  })
385
+ onUpdated(synchronize)
115
386
  onBeforeUnmount(() => {
116
- for (const stop of stops.splice(0)) stop()
117
- if (typeof cleanup === 'function') cleanup()
387
+ unmounted = true
388
+ stopObserving?.()
389
+ disconnect()
118
390
  })
119
391
  /** `ready` settles once the controller has started; a method exposed by the component awaits it. */
120
- return { host, ready: (): Promise<void> | undefined => started }
392
+ return { host, ready: (): Promise<ControllerModule> | undefined => started }
121
393
  }
122
394
 
123
395
  export interface DispatchOptions {
@@ -129,7 +401,59 @@ export interface DispatchOptions {
129
401
  readonly modeled?: readonly string[]
130
402
  }
131
403
 
132
- /** Dispatches a component event to Vue listeners and, for controllers and page code, on the root. */
404
+ class HtmlDiagnosticError extends Error {
405
+ readonly diagnostic: Readonly<{ code: string; message: string }>
406
+
407
+ constructor(code: string, message: string) {
408
+ super(code + ': ' + message)
409
+ this.name = 'HtmlDiagnosticError'
410
+ this.diagnostic = Object.freeze({ code, message })
411
+ }
412
+ }
413
+
414
+ /** Apply HTML Next's event filters before propagation/cancellation actions on the original DOM event. */
415
+ export function runFilteredEvent(
416
+ event: Event,
417
+ modifiers: readonly string[],
418
+ handler: () => void,
419
+ ): void {
420
+ if (modifiers.includes('self') && event.target !== event.currentTarget) return
421
+ if (event instanceof MouseEvent) {
422
+ const buttons: Record<string, number> = { left: 0, middle: 1, right: 2 }
423
+ const filters = modifiers.filter((modifier) => modifier in buttons)
424
+ if (filters.length > 0 && !filters.some((filter) => event.button === buttons[filter])) return
425
+ }
426
+ const systemKeys = ['ctrl', 'shift', 'alt', 'meta'] as const
427
+ for (const key of systemKeys) {
428
+ if (modifiers.includes(key) && !(event as unknown as Record<string, boolean>)[key + 'Key']) {
429
+ return
430
+ }
431
+ }
432
+ if (
433
+ modifiers.includes('exact') && systemKeys.some((key) =>
434
+ !modifiers.includes(key) && (event as unknown as Record<string, boolean>)[key + 'Key']
435
+ )
436
+ ) return
437
+ if (event instanceof KeyboardEvent) {
438
+ const names: Record<string, string> = {
439
+ enter: 'Enter',
440
+ escape: 'Escape',
441
+ space: ' ',
442
+ tab: 'Tab',
443
+ up: 'ArrowUp',
444
+ down: 'ArrowDown',
445
+ left: 'ArrowLeft',
446
+ right: 'ArrowRight',
447
+ }
448
+ const filters = modifiers.filter((modifier) => modifier in names)
449
+ if (filters.length > 0 && !filters.some((filter) => event.key === names[filter])) return
450
+ }
451
+ if (modifiers.includes('prevent')) event.preventDefault()
452
+ if (modifiers.includes('stop')) event.stopPropagation()
453
+ handler()
454
+ }
455
+
456
+ /** Reports declared CustomEvents to Vue and dispatches them through the DOM. */
133
457
  export function createDispatch(
134
458
  root: Readable<HTMLElement | null>,
135
459
  emit?: (name: string, detail: unknown) => void,
@@ -143,9 +467,11 @@ export function createDispatch(
143
467
  return (name, detail) => {
144
468
  const check = checks[name]
145
469
  if (detail !== undefined && check !== undefined && !check(detail)) {
146
- throw new TypeError(`HR002: Event \`${name}\` detail does not satisfy its declared type.`)
470
+ throw new HtmlDiagnosticError(
471
+ 'HR002',
472
+ `Event \`${name}\` detail does not satisfy its declared type.`,
473
+ )
147
474
  }
148
- emit?.(name, detail)
149
475
  if (detail !== null && typeof detail === 'object') {
150
476
  for (const prop of modeled) {
151
477
  if (!(prop in detail)) continue
@@ -156,8 +482,13 @@ export function createDispatch(
156
482
  emit?.(`update:${prop}`, value)
157
483
  }
158
484
  }
159
- return root.value?.dispatchEvent(
160
- new CustomEvent(name, { bubbles: true, composed: true, ...declared[name], detail }),
161
- ) ?? true
485
+ const event = new CustomEvent(name, {
486
+ bubbles: true,
487
+ composed: true,
488
+ ...declared[name],
489
+ detail,
490
+ })
491
+ if (check !== undefined) emit?.(name, event)
492
+ return root.value?.dispatchEvent(event) ?? true
162
493
  }
163
494
  }