@threadlabs/looma 0.19.1 → 0.21.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.
- package/components/shared/trigger.js +9 -4
- package/components/ui-affordance-scope/ui-affordance-scope.html +1 -1
- package/components/ui-avatar/ui-avatar.html +6 -6
- package/components/ui-avatar-group/ui-avatar-group.html +3 -3
- package/components/ui-avatar-group/ui-avatar-group.js +1 -1
- package/components/ui-badge/ui-badge.html +3 -3
- package/components/ui-breadcrumb-item/ui-breadcrumb-item.html +1 -1
- package/components/ui-breadcrumbs/ui-breadcrumbs.html +1 -1
- package/components/ui-button/ui-button.html +17 -16
- package/components/ui-callout/ui-callout.html +1 -1
- package/components/ui-card/ui-card.html +5 -4
- package/components/ui-checkbox/ui-checkbox.html +11 -7
- package/components/ui-cluster/ui-cluster.html +4 -4
- package/components/ui-combobox/ui-combobox.html +299 -74
- package/components/ui-combobox/ui-combobox.js +21 -20
- package/components/ui-container/ui-container.html +2 -2
- package/components/ui-context-menu/ui-context-menu.html +17 -5
- package/components/ui-cover/ui-cover.html +1 -1
- package/components/ui-description-list/ui-description-list.html +3 -3
- package/components/ui-dialog/ui-dialog.html +15 -7
- package/components/ui-disclosure/ui-disclosure.html +17 -8
- package/components/ui-editable/ui-editable.html +20 -9
- package/components/ui-editor-insert-table-grid/ui-editor-insert-table-grid.html +6 -6
- package/components/ui-editor-mention-menu/ui-editor-mention-menu.html +6 -6
- package/components/ui-editor-mention-menu-item/ui-editor-mention-menu-item.html +1 -1
- package/components/ui-editor-slash-menu/ui-editor-slash-menu.html +6 -6
- package/components/ui-editor-slash-menu-group/ui-editor-slash-menu-group.html +1 -1
- package/components/ui-editor-slash-menu-item/ui-editor-slash-menu-item.html +2 -2
- package/components/ui-editor-table-context-menu/ui-editor-table-context-menu.html +33 -13
- package/components/ui-editor-table-overlay/ui-editor-table-overlay.html +107 -29
- package/components/ui-editor-table-overlay/ui-editor-table-overlay.js +5 -5
- package/components/ui-editor-table-toolbar/ui-editor-table-toolbar.html +48 -22
- package/components/ui-floating-action-button/ui-floating-action-button.html +1 -1
- package/components/ui-grid/ui-grid.html +2 -2
- package/components/ui-icon/ui-icon.html +13 -4
- package/components/ui-icon-button/ui-icon-button.html +6 -6
- package/components/ui-input/ui-input.html +28 -6
- package/components/ui-list/ui-list.html +5 -4
- package/components/ui-list-item/ui-list-item.html +2 -2
- package/components/ui-listbox/ui-listbox.html +31 -16
- package/components/ui-menu/ui-menu.html +18 -5
- package/components/ui-menu-group/ui-menu-group.html +1 -1
- package/components/ui-menu-item/ui-menu-item.html +14 -9
- package/components/ui-meter/ui-meter.html +7 -7
- package/components/ui-nav-item/ui-nav-item.html +10 -9
- package/components/ui-page-header/ui-page-header.html +1 -1
- package/components/ui-popover/ui-popover.html +14 -5
- package/components/ui-radio/ui-radio.html +7 -3
- package/components/ui-radio-group/ui-radio-group.html +12 -4
- package/components/ui-reel/ui-reel.html +3 -3
- package/components/ui-scroll-area/ui-scroll-area.html +1 -1
- package/components/ui-search-result-row/ui-search-result-row.html +1 -1
- package/components/ui-search-shell/ui-search-shell.html +7 -3
- package/components/ui-section/ui-section.html +3 -3
- package/components/ui-select/ui-select.html +2 -2
- package/components/ui-separator/ui-separator.html +2 -2
- package/components/ui-sidebar/ui-sidebar.html +13 -6
- package/components/ui-spinner/ui-spinner.html +5 -5
- package/components/ui-stack/ui-stack.html +3 -3
- package/components/ui-status-message/ui-status-message.html +5 -5
- package/components/ui-switch/ui-switch.html +16 -3
- package/components/ui-switcher/ui-switcher.html +3 -3
- package/components/ui-table/ui-table.html +1 -1
- package/components/ui-tabs/ui-tabs.html +14 -9
- package/components/ui-text/ui-text.html +6 -6
- package/components/ui-textarea/ui-textarea.html +10 -2
- package/components/ui-toast/ui-toast.html +8 -4
- package/components/ui-toast-region/ui-toast-region.html +27 -7
- package/components/ui-tooltip/ui-tooltip.html +16 -7
- package/components/ui-tree/ui-tree.html +30 -7
- package/components/ui-tree-item/ui-tree-item.html +21 -17
- package/dist/index.js +1 -1
- package/editor/table-overlay.d.ts +1 -1
- package/package.json +3 -3
- package/styles/ui-action-bar.css +1 -1
- package/styles/ui-affordance-scope.css +1 -1
- package/styles/ui-avatar-group.css +1 -1
- package/styles/ui-avatar.css +1 -1
- package/styles/ui-badge.css +1 -1
- package/styles/ui-breadcrumb-item.css +1 -1
- package/styles/ui-breadcrumbs.css +1 -1
- package/styles/ui-button.css +1 -1
- package/styles/ui-callout.css +1 -1
- package/styles/ui-card.css +1 -1
- package/styles/ui-checkbox.css +1 -1
- package/styles/ui-cluster.css +1 -1
- package/styles/ui-combobox.css +1 -1
- package/styles/ui-container.css +1 -1
- package/styles/ui-context-menu.css +1 -1
- package/styles/ui-cover.css +1 -1
- package/styles/ui-description-item.css +1 -1
- package/styles/ui-description-list.css +1 -1
- package/styles/ui-dialog.css +1 -1
- package/styles/ui-disclosure.css +1 -1
- package/styles/ui-editable.css +1 -1
- package/styles/ui-editor-insert-table-grid.css +1 -1
- package/styles/ui-editor-mention-menu-item.css +1 -1
- package/styles/ui-editor-mention-menu.css +1 -1
- package/styles/ui-editor-slash-menu-group.css +1 -1
- package/styles/ui-editor-slash-menu-item.css +1 -1
- package/styles/ui-editor-slash-menu.css +1 -1
- package/styles/ui-editor-table-context-menu.css +1 -1
- package/styles/ui-editor-table-overlay.css +1 -1
- package/styles/ui-editor-table-toolbar.css +1 -1
- package/styles/ui-editor-toolbar.css +1 -1
- package/styles/ui-floating-action-button.css +1 -1
- package/styles/ui-form-field.css +1 -1
- package/styles/ui-grid.css +1 -1
- package/styles/ui-icon-button.css +1 -1
- package/styles/ui-icon.css +1 -1
- package/styles/ui-input-group.css +1 -1
- package/styles/ui-input.css +1 -1
- package/styles/ui-list-item.css +1 -1
- package/styles/ui-list.css +1 -1
- package/styles/ui-listbox.css +1 -1
- package/styles/ui-menu-group.css +1 -1
- package/styles/ui-menu-item.css +1 -1
- package/styles/ui-menu.css +1 -1
- package/styles/ui-meter.css +1 -1
- package/styles/ui-nav-item.css +1 -1
- package/styles/ui-page-header.css +1 -1
- package/styles/ui-popover.css +1 -1
- package/styles/ui-radio-group.css +1 -1
- package/styles/ui-radio.css +1 -1
- package/styles/ui-reel.css +1 -1
- package/styles/ui-scroll-area.css +1 -1
- package/styles/ui-search-result-row.css +1 -1
- package/styles/ui-search-shell.css +1 -1
- package/styles/ui-section.css +1 -1
- package/styles/ui-select.css +1 -1
- package/styles/ui-separator.css +1 -1
- package/styles/ui-sidebar.css +1 -1
- package/styles/ui-spinner.css +1 -1
- package/styles/ui-stack.css +1 -1
- package/styles/ui-status-message.css +1 -1
- package/styles/ui-switch.css +1 -1
- package/styles/ui-switcher.css +1 -1
- package/styles/ui-table.css +1 -1
- package/styles/ui-tabs.css +1 -1
- package/styles/ui-text.css +1 -1
- package/styles/ui-textarea.css +1 -1
- package/styles/ui-toast-region.css +1 -1
- package/styles/ui-toast.css +1 -1
- package/styles/ui-tooltip.css +1 -1
- package/styles/ui-top-bar.css +1 -1
- package/styles/ui-tree-item.css +1 -1
- package/styles/ui-tree.css +1 -1
- package/vanilla/UiActionBar.d.ts +1 -1
- package/vanilla/UiActionBar.js +5 -1
- package/vanilla/UiAffordanceScope.d.ts +1 -1
- package/vanilla/UiAffordanceScope.js +3 -2
- package/vanilla/UiAvatar.d.ts +1 -1
- package/vanilla/UiAvatar.js +4 -3
- package/vanilla/UiAvatarGroup.d.ts +1 -1
- package/vanilla/UiAvatarGroup.js +3 -2
- package/vanilla/UiBadge.d.ts +1 -1
- package/vanilla/UiBadge.js +2 -1
- package/vanilla/UiBreadcrumbItem.d.ts +1 -1
- package/vanilla/UiBreadcrumbItem.js +2 -1
- package/vanilla/UiBreadcrumbs.d.ts +1 -1
- package/vanilla/UiBreadcrumbs.js +4 -7
- package/vanilla/UiButton.d.ts +1 -1
- package/vanilla/UiButton.js +6 -4
- package/vanilla/UiCallout.d.ts +1 -1
- package/vanilla/UiCallout.js +3 -2
- package/vanilla/UiCard.d.ts +1 -1
- package/vanilla/UiCard.js +6 -2
- package/vanilla/UiCheckbox.d.ts +1 -1
- package/vanilla/UiCheckbox.js +4 -2
- package/vanilla/UiCluster.d.ts +1 -1
- package/vanilla/UiCluster.js +2 -1
- package/vanilla/UiCombobox.d.ts +3 -2
- package/vanilla/UiCombobox.js +8 -2
- package/vanilla/UiContainer.d.ts +1 -1
- package/vanilla/UiContainer.js +2 -1
- package/vanilla/UiContextMenu.d.ts +1 -1
- package/vanilla/UiContextMenu.js +3 -2
- package/vanilla/UiCover.d.ts +1 -1
- package/vanilla/UiCover.js +4 -5
- package/vanilla/UiDescriptionItem.d.ts +1 -1
- package/vanilla/UiDescriptionItem.js +4 -7
- package/vanilla/UiDescriptionList.d.ts +1 -1
- package/vanilla/UiDescriptionList.js +2 -1
- package/vanilla/UiDialog.d.ts +1 -1
- package/vanilla/UiDialog.js +4 -2
- package/vanilla/UiDisclosure.d.ts +1 -1
- package/vanilla/UiDisclosure.js +4 -2
- package/vanilla/UiEditable.d.ts +1 -1
- package/vanilla/UiEditable.js +2 -2
- package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
- package/vanilla/UiEditorInsertTableGrid.js +1 -1
- package/vanilla/UiEditorMentionMenu.d.ts +1 -1
- package/vanilla/UiEditorMentionMenu.js +5 -2
- package/vanilla/UiEditorMentionMenuItem.d.ts +1 -1
- package/vanilla/UiEditorMentionMenuItem.js +3 -1
- package/vanilla/UiEditorSlashMenu.d.ts +1 -1
- package/vanilla/UiEditorSlashMenu.js +6 -2
- package/vanilla/UiEditorSlashMenuGroup.d.ts +1 -1
- package/vanilla/UiEditorSlashMenuGroup.js +4 -7
- package/vanilla/UiEditorSlashMenuItem.d.ts +1 -1
- package/vanilla/UiEditorSlashMenuItem.js +2 -1
- package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
- package/vanilla/UiEditorTableContextMenu.js +2 -2
- package/vanilla/UiEditorTableOverlay.d.ts +12 -2
- package/vanilla/UiEditorTableOverlay.js +2 -2
- package/vanilla/UiEditorTableToolbar.d.ts +1 -1
- package/vanilla/UiEditorTableToolbar.js +2 -2
- package/vanilla/UiEditorToolbar.d.ts +1 -1
- package/vanilla/UiEditorToolbar.js +2 -1
- package/vanilla/UiFloatingActionButton.d.ts +1 -1
- package/vanilla/UiFloatingActionButton.js +2 -1
- package/vanilla/UiFormField.d.ts +1 -1
- package/vanilla/UiFormField.js +6 -1
- package/vanilla/UiGrid.d.ts +1 -1
- package/vanilla/UiGrid.js +4 -3
- package/vanilla/UiIcon.d.ts +1 -1
- package/vanilla/UiIcon.js +1 -1
- package/vanilla/UiIconButton.d.ts +1 -1
- package/vanilla/UiIconButton.js +4 -3
- package/vanilla/UiInput.d.ts +5 -4
- package/vanilla/UiInput.js +16 -13
- package/vanilla/UiInputGroup.d.ts +1 -1
- package/vanilla/UiInputGroup.js +5 -1
- package/vanilla/UiList.d.ts +1 -1
- package/vanilla/UiList.js +4 -2
- package/vanilla/UiListItem.d.ts +1 -1
- package/vanilla/UiListItem.js +5 -1
- package/vanilla/UiListbox.d.ts +1 -1
- package/vanilla/UiListbox.js +3 -2
- package/vanilla/UiMenu.d.ts +1 -1
- package/vanilla/UiMenu.js +3 -2
- package/vanilla/UiMenuGroup.d.ts +1 -1
- package/vanilla/UiMenuGroup.js +2 -1
- package/vanilla/UiMenuItem.d.ts +1 -1
- package/vanilla/UiMenuItem.js +6 -2
- package/vanilla/UiMeter.d.ts +1 -1
- package/vanilla/UiMeter.js +2 -2
- package/vanilla/UiNavItem.d.ts +2 -2
- package/vanilla/UiNavItem.js +11 -5
- package/vanilla/UiPageHeader.d.ts +1 -1
- package/vanilla/UiPageHeader.js +8 -5
- package/vanilla/UiPopover.d.ts +1 -1
- package/vanilla/UiPopover.js +3 -2
- package/vanilla/UiRadio.d.ts +1 -1
- package/vanilla/UiRadio.js +4 -2
- package/vanilla/UiRadioGroup.d.ts +1 -1
- package/vanilla/UiRadioGroup.js +3 -2
- package/vanilla/UiReel.d.ts +1 -1
- package/vanilla/UiReel.js +2 -1
- package/vanilla/UiScrollArea.d.ts +1 -1
- package/vanilla/UiScrollArea.js +3 -2
- package/vanilla/UiSearchResultRow.d.ts +1 -1
- package/vanilla/UiSearchResultRow.js +6 -1
- package/vanilla/UiSearchShell.d.ts +1 -1
- package/vanilla/UiSearchShell.js +6 -2
- package/vanilla/UiSection.d.ts +1 -1
- package/vanilla/UiSection.js +5 -2
- package/vanilla/UiSelect.d.ts +1 -1
- package/vanilla/UiSelect.js +3 -2
- package/vanilla/UiSeparator.d.ts +1 -1
- package/vanilla/UiSeparator.js +3 -7
- package/vanilla/UiSidebar.d.ts +1 -1
- package/vanilla/UiSidebar.js +3 -2
- package/vanilla/UiSpinner.d.ts +1 -1
- package/vanilla/UiSpinner.js +2 -2
- package/vanilla/UiStack.d.ts +1 -1
- package/vanilla/UiStack.js +2 -1
- package/vanilla/UiStatusMessage.d.ts +1 -1
- package/vanilla/UiStatusMessage.js +4 -2
- package/vanilla/UiSwitch.d.ts +1 -1
- package/vanilla/UiSwitch.js +4 -2
- package/vanilla/UiSwitcher.d.ts +1 -1
- package/vanilla/UiSwitcher.js +3 -2
- package/vanilla/UiTable.d.ts +1 -1
- package/vanilla/UiTable.js +3 -2
- package/vanilla/UiTabs.d.ts +1 -1
- package/vanilla/UiTabs.js +4 -2
- package/vanilla/UiText.d.ts +1 -1
- package/vanilla/UiText.js +13 -2
- package/vanilla/UiTextarea.d.ts +1 -1
- package/vanilla/UiTextarea.js +3 -3
- package/vanilla/UiToast.d.ts +1 -1
- package/vanilla/UiToast.js +4 -2
- package/vanilla/UiToastRegion.d.ts +1 -1
- package/vanilla/UiToastRegion.js +3 -2
- package/vanilla/UiTooltip.d.ts +1 -1
- package/vanilla/UiTooltip.js +3 -2
- package/vanilla/UiTopBar.d.ts +1 -1
- package/vanilla/UiTopBar.js +5 -1
- package/vanilla/UiTree.d.ts +1 -1
- package/vanilla/UiTree.js +3 -2
- package/vanilla/UiTreeItem.d.ts +1 -1
- package/vanilla/UiTreeItem.js +8 -4
- package/vue/UiActionBar.vue +33 -2
- package/vue/UiAffordanceScope.d.ts +23 -8
- package/vue/UiAffordanceScope.vue +90 -17
- package/vue/UiAvatar.d.ts +77 -19
- package/vue/UiAvatar.vue +151 -31
- package/vue/UiAvatarGroup.d.ts +50 -13
- package/vue/UiAvatarGroup.vue +121 -23
- package/vue/UiBadge.d.ts +32 -10
- package/vue/UiBadge.vue +104 -17
- package/vue/UiBreadcrumbItem.d.ts +14 -6
- package/vue/UiBreadcrumbItem.vue +82 -15
- package/vue/UiBreadcrumbs.d.ts +14 -6
- package/vue/UiBreadcrumbs.vue +78 -10
- package/vue/UiButton.d.ts +122 -27
- package/vue/UiButton.vue +288 -64
- package/vue/UiCallout.d.ts +14 -6
- package/vue/UiCallout.vue +84 -16
- package/vue/UiCard.d.ts +41 -12
- package/vue/UiCard.vue +149 -25
- package/vue/UiCheckbox.d.ts +85 -28
- package/vue/UiCheckbox.vue +173 -43
- package/vue/UiCluster.d.ts +41 -7
- package/vue/UiCluster.vue +122 -13
- package/vue/UiCombobox.d.ts +303 -110
- package/vue/UiCombobox.vue +723 -412
- package/vue/UiContainer.d.ts +23 -5
- package/vue/UiContainer.vue +89 -9
- package/vue/UiContextMenu.d.ts +38 -23
- package/vue/UiContextMenu.vue +113 -38
- package/vue/UiCover.d.ts +14 -6
- package/vue/UiCover.vue +76 -12
- package/vue/UiDescriptionItem.d.ts +14 -6
- package/vue/UiDescriptionItem.vue +78 -11
- package/vue/UiDescriptionList.d.ts +32 -9
- package/vue/UiDescriptionList.vue +106 -16
- package/vue/UiDialog.d.ts +89 -30
- package/vue/UiDialog.vue +168 -38
- package/vue/UiDisclosure.d.ts +70 -27
- package/vue/UiDisclosure.vue +149 -36
- package/vue/UiEditable.d.ts +119 -41
- package/vue/UiEditable.vue +220 -62
- package/vue/UiEditorInsertTableGrid.d.ts +46 -17
- package/vue/UiEditorInsertTableGrid.vue +215 -40
- package/vue/UiEditorMentionMenu.d.ts +128 -41
- package/vue/UiEditorMentionMenu.vue +211 -37
- package/vue/UiEditorMentionMenuItem.d.ts +32 -10
- package/vue/UiEditorMentionMenuItem.vue +98 -17
- package/vue/UiEditorSlashMenu.d.ts +110 -37
- package/vue/UiEditorSlashMenu.vue +189 -31
- package/vue/UiEditorSlashMenuGroup.d.ts +14 -6
- package/vue/UiEditorSlashMenuGroup.vue +80 -12
- package/vue/UiEditorSlashMenuItem.d.ts +50 -14
- package/vue/UiEditorSlashMenuItem.vue +120 -23
- package/vue/UiEditorTableContextMenu.d.ts +64 -20
- package/vue/UiEditorTableContextMenu.vue +326 -91
- package/vue/UiEditorTableOverlay.d.ts +170 -44
- package/vue/UiEditorTableOverlay.vue +420 -149
- package/vue/UiEditorTableToolbar.d.ts +64 -20
- package/vue/UiEditorTableToolbar.vue +344 -107
- package/vue/UiEditorToolbar.d.ts +14 -6
- package/vue/UiEditorToolbar.vue +79 -15
- package/vue/UiFloatingActionButton.d.ts +32 -10
- package/vue/UiFloatingActionButton.vue +96 -18
- package/vue/UiFormField.d.ts +32 -10
- package/vue/UiFormField.vue +99 -19
- package/vue/UiGrid.d.ts +32 -6
- package/vue/UiGrid.vue +95 -11
- package/vue/UiIcon.d.ts +14 -6
- package/vue/UiIcon.vue +99 -14
- package/vue/UiIconButton.d.ts +77 -19
- package/vue/UiIconButton.vue +176 -39
- package/vue/UiInput.d.ts +50 -19
- package/vue/UiInput.vue +326 -33
- package/vue/UiInputGroup.d.ts +14 -6
- package/vue/UiInputGroup.vue +79 -15
- package/vue/UiList.d.ts +41 -12
- package/vue/UiList.vue +125 -22
- package/vue/UiListItem.d.ts +23 -8
- package/vue/UiListItem.vue +88 -16
- package/vue/UiListbox.d.ts +86 -27
- package/vue/UiListbox.vue +272 -64
- package/vue/UiMenu.d.ts +69 -33
- package/vue/UiMenu.vue +142 -38
- package/vue/UiMenuGroup.d.ts +14 -6
- package/vue/UiMenuGroup.vue +80 -11
- package/vue/UiMenuItem.d.ts +61 -25
- package/vue/UiMenuItem.vue +174 -45
- package/vue/UiMeter.d.ts +68 -18
- package/vue/UiMeter.vue +215 -41
- package/vue/UiNavItem.d.ts +50 -11
- package/vue/UiNavItem.vue +163 -29
- package/vue/UiPageHeader.d.ts +14 -6
- package/vue/UiPageHeader.vue +75 -12
- package/vue/UiPopover.d.ts +43 -21
- package/vue/UiPopover.vue +147 -27
- package/vue/UiRadio.d.ts +67 -24
- package/vue/UiRadio.vue +147 -36
- package/vue/UiRadioGroup.d.ts +79 -29
- package/vue/UiRadioGroup.vue +162 -41
- package/vue/UiReel.d.ts +32 -6
- package/vue/UiReel.vue +97 -11
- package/vue/UiScrollArea.d.ts +14 -6
- package/vue/UiScrollArea.vue +83 -14
- package/vue/UiSearchResultRow.d.ts +23 -8
- package/vue/UiSearchResultRow.vue +86 -16
- package/vue/UiSearchShell.d.ts +48 -19
- package/vue/UiSearchShell.vue +120 -26
- package/vue/UiSection.d.ts +32 -10
- package/vue/UiSection.vue +103 -17
- package/vue/UiSelect.d.ts +59 -17
- package/vue/UiSelect.vue +140 -29
- package/vue/UiSeparator.d.ts +14 -6
- package/vue/UiSeparator.vue +80 -9
- package/vue/UiSidebar.d.ts +95 -31
- package/vue/UiSidebar.vue +172 -39
- package/vue/UiSpinner.d.ts +23 -8
- package/vue/UiSpinner.vue +115 -24
- package/vue/UiStack.d.ts +32 -6
- package/vue/UiStack.vue +107 -11
- package/vue/UiStatusMessage.d.ts +32 -10
- package/vue/UiStatusMessage.vue +109 -19
- package/vue/UiSwitch.d.ts +67 -24
- package/vue/UiSwitch.vue +147 -36
- package/vue/UiSwitcher.d.ts +41 -7
- package/vue/UiSwitcher.vue +118 -15
- package/vue/UiTable.d.ts +23 -8
- package/vue/UiTable.vue +91 -17
- package/vue/UiTabs.d.ts +66 -23
- package/vue/UiTabs.vue +230 -44
- package/vue/UiText.d.ts +68 -18
- package/vue/UiText.vue +308 -48
- package/vue/UiTextarea.d.ts +84 -21
- package/vue/UiTextarea.vue +172 -38
- package/vue/UiToast.d.ts +28 -13
- package/vue/UiToast.vue +103 -24
- package/vue/UiToastRegion.d.ts +29 -14
- package/vue/UiToastRegion.vue +202 -47
- package/vue/UiTooltip.d.ts +81 -31
- package/vue/UiTooltip.vue +192 -37
- package/vue/UiTopBar.vue +33 -2
- package/vue/UiTree.d.ts +72 -29
- package/vue/UiTree.vue +170 -49
- package/vue/UiTreeItem.d.ts +136 -35
- package/vue/UiTreeItem.vue +227 -61
- package/vue/chunks/UiActionBar.js +16 -3
- package/vue/chunks/UiAffordanceScope.js +66 -11
- package/vue/chunks/UiAvatar.js +121 -20
- package/vue/chunks/UiAvatarGroup.js +94 -15
- package/vue/chunks/UiBadge.js +82 -10
- package/vue/chunks/UiBreadcrumbItem.js +43 -9
- package/vue/chunks/UiBreadcrumbs.js +41 -5
- package/vue/chunks/UiButton.js +237 -51
- package/vue/chunks/UiCallout.js +53 -11
- package/vue/chunks/UiCard.js +145 -18
- package/vue/chunks/UiCheckbox.js +130 -30
- package/vue/chunks/UiCluster.js +99 -12
- package/vue/chunks/UiCombobox.js +545 -162
- package/vue/chunks/UiContainer.js +65 -7
- package/vue/chunks/UiContextMenu.js +56 -11
- package/vue/chunks/UiCover.js +41 -6
- package/vue/chunks/UiDescriptionItem.js +39 -4
- package/vue/chunks/UiDescriptionList.js +80 -10
- package/vue/chunks/UiDialog.js +125 -18
- package/vue/chunks/UiDisclosure.js +102 -17
- package/vue/chunks/UiEditable.js +154 -29
- package/vue/chunks/UiEditorInsertTableGrid.js +154 -31
- package/vue/chunks/UiEditorMentionMenu.js +221 -18
- package/vue/chunks/UiEditorMentionMenuItem.js +64 -7
- package/vue/chunks/UiEditorSlashMenu.js +201 -14
- package/vue/chunks/UiEditorSlashMenuGroup.js +43 -9
- package/vue/chunks/UiEditorSlashMenuItem.js +80 -14
- package/vue/chunks/UiEditorTableContextMenu.js +220 -49
- package/vue/chunks/UiEditorTableOverlay.js +390 -85
- package/vue/chunks/UiEditorTableToolbar.js +248 -71
- package/vue/chunks/UiEditorToolbar.js +44 -10
- package/vue/chunks/UiFloatingActionButton.js +57 -9
- package/vue/chunks/UiFormField.js +63 -12
- package/vue/chunks/UiGrid.js +80 -9
- package/vue/chunks/UiIcon.js +73 -16
- package/vue/chunks/UiIconButton.js +126 -28
- package/vue/chunks/UiInput.js +328 -22
- package/vue/chunks/UiInputGroup.js +44 -10
- package/vue/chunks/UiList.js +104 -15
- package/vue/chunks/UiListItem.js +57 -8
- package/vue/chunks/UiListbox.js +208 -49
- package/vue/chunks/UiMenu.js +88 -15
- package/vue/chunks/UiMenuGroup.js +41 -5
- package/vue/chunks/UiMenuItem.js +111 -32
- package/vue/chunks/UiMeter.js +166 -36
- package/vue/chunks/UiNavItem.js +133 -37
- package/vue/chunks/UiPageHeader.js +41 -6
- package/vue/chunks/UiPopover.js +81 -11
- package/vue/chunks/UiRadio.js +115 -24
- package/vue/chunks/UiRadioGroup.js +108 -19
- package/vue/chunks/UiReel.js +81 -10
- package/vue/chunks/UiScrollArea.js +47 -10
- package/vue/chunks/UiSearchResultRow.js +47 -8
- package/vue/chunks/UiSearchShell.js +84 -24
- package/vue/chunks/UiSection.js +77 -10
- package/vue/chunks/UiSelect.js +108 -20
- package/vue/chunks/UiSeparator.js +41 -5
- package/vue/chunks/UiSidebar.js +136 -20
- package/vue/chunks/UiSpinner.js +64 -19
- package/vue/chunks/UiStack.js +87 -10
- package/vue/chunks/UiStatusMessage.js +82 -12
- package/vue/chunks/UiSwitch.js +115 -24
- package/vue/chunks/UiSwitcher.js +103 -15
- package/vue/chunks/UiTable.js +63 -11
- package/vue/chunks/UiTabs.js +170 -30
- package/vue/chunks/UiText.js +365 -38
- package/vue/chunks/UiTextarea.js +132 -26
- package/vue/chunks/UiToast.js +70 -12
- package/vue/chunks/UiToastRegion.js +154 -33
- package/vue/chunks/UiTooltip.js +124 -16
- package/vue/chunks/UiTopBar.js +16 -3
- package/vue/chunks/UiTree.js +107 -15
- package/vue/chunks/UiTreeItem.js +167 -43
- package/vue/chunks/control.js +171 -0
- package/vue/chunks/host.js +170 -27
- package/vue/chunks/props.js +477 -0
- package/vue/components.css +1192 -1192
- package/vue/editor/index.js +58 -15
- package/vue/editor/primitives.d.ts +52 -2
- package/vue/host.ts +370 -39
package/vue/editor/index.js
CHANGED
|
@@ -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: (
|
|
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: (
|
|
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: (
|
|
1884
|
-
slash.selectedIndex = index;
|
|
1883
|
+
onHighlight: (event) => {
|
|
1884
|
+
slash.selectedIndex = event.detail.index;
|
|
1885
1885
|
},
|
|
1886
|
-
onSelect: (
|
|
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: (
|
|
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: (
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
2
|
-
import {
|
|
1
|
+
// Generated by HTML Next 1.0.0-alpha.12 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
|
|
27
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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
|
-
|
|
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'
|
|
66
|
-
const
|
|
67
|
-
|
|
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<
|
|
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
|
-
|
|
112
|
-
|
|
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
|
-
|
|
117
|
-
|
|
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<
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
}
|