@workbench-kit/react 0.0.2-prototype.0.1.4 → 0.0.2-prototype.0.2.10
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/README.md +87 -0
- package/package.json +37 -27
- package/src/brand/TilepaperAppIcon.tsx +181 -0
- package/src/brand/index.ts +2 -0
- package/src/brand/tilepaper-app-icon-geometry.ts +201 -0
- package/src/icons/WorkbenchIcon.tsx +57 -0
- package/src/icons/WorkbenchIconContext.tsx +25 -0
- package/src/icons/file-icon.ts +154 -0
- package/src/icons/index.ts +17 -0
- package/src/icons/resolveWorkbenchIcon.ts +48 -0
- package/src/icons/types.ts +28 -0
- package/src/index.ts +278 -88
- package/src/jdw/JdwPreview.tsx +165 -8
- package/src/jdw/JdwPreviewViewport.tsx +190 -0
- package/src/jdw/JsonCodeEditorPane.tsx +172 -21
- package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +101 -0
- package/src/jdw/createBuiltinJdwRegistry.ts +330 -5
- package/src/jdw/cssRenderBackend.tsx +96 -7
- package/src/jdw/document.ts +0 -3
- package/src/jdw/fixtures/jdw-sample-screens.ts +10 -8
- package/src/jdw/index.ts +9 -4
- package/src/jdw/jdw-preview-viewport.css +41 -0
- package/src/jdw/renderJdw.tsx +49 -8
- package/src/json-config/JsonConfigWorkbench.tsx +12 -15
- package/src/layout/ViewEmptyState.tsx +14 -0
- package/src/layout/WorkbenchCanvas.tsx +113 -6
- package/src/layout/WorkbenchLayout.tsx +3 -0
- package/src/layout/WorkbenchLayoutBase.tsx +43 -2
- package/src/layout/WorkbenchMediaPreviewViewport.tsx +122 -0
- package/src/layout/WorkbenchPropertyOverrideLabel.tsx +90 -0
- package/src/layout/WorkbenchPropertyPanel.tsx +153 -17
- package/src/layout/WorkbenchPropertySearch.tsx +51 -0
- package/src/layout/WorkbenchTree.tsx +9 -10
- package/src/layout/canvas/canvas-drag-ghost.css +21 -0
- package/src/layout/canvas/canvas-drag-preview-frame.css +15 -0
- package/src/layout/canvas/canvas-drop-indicator.css +16 -0
- package/src/layout/canvas/canvas-frame-handle.css +37 -0
- package/src/layout/canvas/canvas-frame-surface.css +24 -0
- package/src/layout/canvas/canvas-guide-block.css +17 -0
- package/src/layout/canvas/canvas-guide-layer.css +6 -0
- package/src/layout/canvas/canvas-guide-line.css +22 -0
- package/src/layout/canvas/canvas-item-badge.css +23 -0
- package/src/layout/canvas/canvas-item-frame.css +54 -0
- package/src/layout/canvas/canvas-pane-surface.css +9 -0
- package/src/layout/canvas/canvas-placeholder.css +21 -0
- package/src/layout/canvas/canvas-resize-frame.css +9 -0
- package/src/layout/canvas/canvas-resize-handle.css +74 -0
- package/src/layout/canvas/canvas-resize-preview.css +11 -0
- package/src/layout/canvas/canvas-selection-marquee.css +14 -0
- package/src/layout/canvas/canvas-viewport.css +18 -0
- package/src/layout/canvas/index.css +19 -0
- package/src/layout/canvas/preview-canvas.css +144 -0
- package/src/layout/editor/editor-body.css +9 -0
- package/src/layout/editor/editor-bottom-panel.css +44 -0
- package/src/layout/editor/editor-frame.css +14 -0
- package/src/layout/editor/editor-viewport.css +7 -0
- package/src/layout/editor/floating-menu.css +91 -0
- package/src/layout/editor/index.css +10 -0
- package/src/layout/editor/parse-error.css +9 -0
- package/src/layout/editor/problem-item.css +52 -0
- package/src/layout/editor/problem-list.css +7 -0
- package/src/layout/editor/render-surface.css +13 -0
- package/src/layout/fillScrollContract.ts +49 -0
- package/src/layout/fullscreen/fullscreen-backdrop.css +31 -0
- package/src/layout/fullscreen/fullscreen-button.css +44 -0
- package/src/layout/fullscreen/fullscreen-carousel.css +20 -0
- package/src/layout/fullscreen/fullscreen-content.css +8 -0
- package/src/layout/fullscreen/fullscreen-empty.css +16 -0
- package/src/layout/fullscreen/fullscreen-header.css +77 -0
- package/src/layout/fullscreen/fullscreen-hero.css +41 -0
- package/src/layout/fullscreen/fullscreen-nav-button.css +29 -0
- package/src/layout/fullscreen/fullscreen-option.css +83 -0
- package/src/layout/fullscreen/fullscreen-pill-row.css +6 -0
- package/src/layout/fullscreen/fullscreen-pill.css +10 -0
- package/src/layout/fullscreen/fullscreen-root.css +11 -0
- package/src/layout/fullscreen/index.css +13 -0
- package/src/layout/index.ts +156 -0
- package/src/layout/layout-base/banner.css +32 -0
- package/src/layout/layout-base/center.css +7 -0
- package/src/layout/layout-base/column.css +7 -0
- package/src/layout/layout-base/divider.css +5 -0
- package/src/layout/layout-base/empty.css +12 -0
- package/src/layout/layout-base/fill-scroll.css +36 -0
- package/src/layout/layout-base/fill.css +18 -0
- package/src/layout/layout-base/index.css +13 -0
- package/src/layout/layout-base/pane.css +6 -0
- package/src/layout/layout-base/panel-scroll.css +5 -0
- package/src/layout/layout-base/panel-surface.css +14 -0
- package/src/layout/layout-base/root.css +9 -0
- package/src/layout/layout-base/section-title.css +8 -0
- package/src/layout/layout.css +10 -0
- package/src/layout/layoutHelpers.ts +4 -2
- package/src/layout/media/index.css +2 -0
- package/src/layout/media/media-preview-viewport.css +69 -0
- package/src/layout/{Panel.tsx → panel/Panel.tsx} +29 -40
- package/src/layout/panel/TemplateGallery.tsx +90 -0
- package/src/layout/panel/WorkbenchAuthoringShell.tsx +57 -0
- package/src/layout/panel/WorkbenchLabeledPane.tsx +81 -0
- package/src/layout/panel/WorkbenchSidebarStack.tsx +15 -0
- package/src/layout/panel/filter-bar.css +59 -0
- package/src/layout/panel/index.css +7 -0
- package/src/layout/panel/index.ts +70 -0
- package/src/layout/panel/preview-pane.css +63 -0
- package/src/layout/panel/template-gallery.css +131 -0
- package/src/layout/panel/workbench-authoring-shell.css +48 -0
- package/src/layout/panel/workbench-labeled-pane.css +69 -0
- package/src/layout/panel/workbench-sidebar-stack.css +18 -0
- package/src/layout/property/color-input.css +8 -0
- package/src/layout/property/color-row.css +6 -0
- package/src/layout/property/index.css +15 -0
- package/src/layout/property/property-card.css +8 -0
- package/src/layout/property/property-grid.css +24 -0
- package/src/layout/property/property-hint.css +4 -0
- package/src/layout/property/property-inline.css +10 -0
- package/src/layout/property/property-key-value.css +29 -0
- package/src/layout/property/property-override-label.css +34 -0
- package/src/layout/property/property-panel.css +20 -0
- package/src/layout/property/property-row.css +17 -0
- package/src/layout/property/property-search.css +43 -0
- package/src/layout/property/property-section.css +97 -0
- package/src/layout/property/property-stack.css +11 -0
- package/src/layout/property/property-toggle.css +14 -0
- package/src/layout/propertyFieldFilter.ts +84 -0
- package/src/layout/sidebar/SideBarViewFrame.tsx +235 -0
- package/src/layout/sidebar/SideBarViewTabStrip.tsx +60 -0
- package/src/layout/sidebar/SideBarViewTitleMenu.tsx +75 -0
- package/src/layout/sidebar/SidebarActionIconBar.tsx +242 -0
- package/src/layout/sidebar/SidebarSectionNestingContext.tsx +21 -0
- package/src/layout/sidebar/SidebarSlotChrome.tsx +32 -0
- package/src/layout/sidebar/SidebarToolbar.tsx +10 -0
- package/src/layout/sidebar/WorkbenchActionSidebar.tsx +73 -0
- package/src/layout/{WorkbenchSidebarActions.tsx → sidebar/WorkbenchSidebarActions.tsx} +105 -51
- package/src/layout/sidebar/WorkbenchSidebarSectionStack.tsx +165 -0
- package/src/layout/sidebar/index.css +5 -0
- package/src/layout/sidebar/index.ts +55 -0
- package/src/layout/sidebar/sidebar-chrome.css +95 -0
- package/src/layout/sidebar/sidebar-section-stack.css +25 -0
- package/src/layout/sidebar/sidebar-section.css +124 -0
- package/src/layout/sidebar/sidebar-view.css +290 -0
- package/src/layout/tree/drag-preview.css +25 -0
- package/src/layout/tree/index.css +10 -0
- package/src/layout/tree/template-glyph.css +96 -0
- package/src/layout/tree/tree-action.css +20 -0
- package/src/layout/tree/tree-drag-overlay.css +13 -0
- package/src/layout/tree/tree-drop-line.css +17 -0
- package/src/layout/tree/tree-drop-zone.css +13 -0
- package/src/layout/tree/tree-expander.css +23 -0
- package/src/layout/tree/tree-item.css +93 -0
- package/src/layout/tree/tree.css +49 -0
- package/src/layout/usePreviewViewport.ts +428 -0
- package/src/modal/ConfirmDialog.tsx +1 -1
- package/src/modal/Modal.tsx +184 -311
- package/src/modal/ModalResizeHandles.tsx +40 -0
- package/src/modal/ModalTitlebar.tsx +86 -0
- package/src/modal/modal.css +291 -0
- package/src/modal/modalContainer.ts +36 -0
- package/src/modal/modalPosition.ts +36 -0
- package/src/modal/modalSize.ts +84 -0
- package/src/modal/modalTypes.ts +13 -0
- package/src/modal/useModalContainerViewport.ts +41 -0
- package/src/modal/useModalDrag.ts +118 -0
- package/src/modal/useModalFocusTrap.ts +142 -0
- package/src/modal/useModalResize.ts +122 -0
- package/src/modal/useModalWindowFrame.ts +122 -0
- package/src/overlay/ContextMenu.tsx +28 -50
- package/src/overlay/clampFixedOverlayPosition.ts +22 -0
- package/src/overlay/context-menu.css +127 -0
- package/src/overlay/index.ts +31 -0
- package/src/overlay/measureAnchoredOverlayPanel.ts +107 -0
- package/src/overlay/overlay.css +2 -0
- package/src/overlay/pointerPassthroughRegion.ts +83 -0
- package/src/overlay/useAnchoredOverlayPanel.ts +222 -0
- package/src/overlay/useClampedFixedOverlayPosition.ts +27 -0
- package/src/overlay/useContextMenuState.ts +59 -0
- package/src/overlay/useFixedOverlayDismiss.ts +49 -0
- package/src/overlay/usePointerPassthroughRegion.ts +87 -0
- package/src/primitives/{AbsoluteBox.tsx → absolute-box/AbsoluteBox.tsx} +5 -5
- package/src/primitives/absolute-box/index.ts +1 -0
- package/src/primitives/{Badge.tsx → badge/Badge.tsx} +4 -2
- package/src/primitives/badge/badge.css +20 -0
- package/src/primitives/badge/index.ts +1 -0
- package/src/primitives/{Button.tsx → button/Button.tsx} +7 -6
- package/src/primitives/button/button.css +76 -0
- package/src/primitives/button/index.ts +1 -0
- package/src/primitives/catalog-browse-card/CatalogBrowseCard.tsx +121 -0
- package/src/primitives/catalog-browse-card/catalog-browse-card.css +175 -0
- package/src/primitives/catalog-browse-card/index.ts +1 -0
- package/src/primitives/catalog-browse-pane/CatalogBrowseFacetChips.tsx +59 -0
- package/src/primitives/catalog-browse-pane/CatalogBrowsePane.tsx +360 -0
- package/src/primitives/catalog-browse-pane/catalog-browse-facet-chips.css +8 -0
- package/src/primitives/catalog-browse-pane/catalog-browse-pane.css +84 -0
- package/src/primitives/catalog-browse-pane/filterCatalogBrowseItems.ts +27 -0
- package/src/primitives/catalog-browse-pane/index.ts +3 -0
- package/src/primitives/catalog-filter-overlay/CatalogFilterOverlay.tsx +73 -0
- package/src/primitives/catalog-filter-overlay/catalog-filter-overlay.css +65 -0
- package/src/primitives/catalog-filter-overlay/index.ts +1 -0
- package/src/primitives/checkbox/Checkbox.tsx +40 -0
- package/src/primitives/checkbox/checkbox.css +81 -0
- package/src/primitives/checkbox/index.ts +1 -0
- package/src/primitives/chip/Chip.tsx +43 -0
- package/src/primitives/chip/chip.css +110 -0
- package/src/primitives/chip/index.ts +2 -0
- package/src/primitives/clearable-text-input/ClearableTextInput.tsx +78 -0
- package/src/primitives/clearable-text-input/clearable-text-input.css +15 -0
- package/src/primitives/clearable-text-input/index.ts +1 -0
- package/src/primitives/codicon/Codicon.tsx +20 -0
- package/src/primitives/codicon/index.ts +1 -0
- package/src/primitives/{EmptyState.tsx → empty-state/EmptyState.tsx} +9 -3
- package/src/primitives/empty-state/empty-state.css +20 -0
- package/src/primitives/empty-state/index.ts +1 -0
- package/src/primitives/external-link-button/ExternalLinkButton.tsx +56 -0
- package/src/primitives/external-link-button/index.ts +1 -0
- package/src/primitives/{Field.tsx → field/Field.tsx} +2 -1
- package/src/primitives/field/field.css +51 -0
- package/src/primitives/field/index.ts +1 -0
- package/src/primitives/file-icon/FileIcon.tsx +21 -0
- package/src/primitives/file-icon/index.ts +1 -0
- package/src/primitives/{IconButton.tsx → icon-button/IconButton.tsx} +7 -5
- package/src/primitives/icon-button/icon-button.css +46 -0
- package/src/primitives/icon-button/index.ts +1 -0
- package/src/primitives/index.ts +210 -50
- package/src/primitives/library-detail-layout/LibraryDetailLayout.tsx +135 -0
- package/src/primitives/library-detail-layout/index.ts +1 -0
- package/src/primitives/library-detail-layout/library-detail-layout.css +169 -0
- package/src/primitives/library-facet-filter-panel/LibraryFacetFilterPanel.tsx +454 -0
- package/src/primitives/library-facet-filter-panel/index.ts +1 -0
- package/src/primitives/library-facet-filter-panel/library-facet-filter-panel.css +205 -0
- package/src/primitives/library-facet-filter-strip/LibraryFacetFilterStrip.tsx +527 -0
- package/src/primitives/library-facet-filter-strip/index.ts +1 -0
- package/src/primitives/library-facet-filter-strip/library-facet-filter-strip.css +31 -0
- package/src/primitives/{List.tsx → list/List.tsx} +15 -6
- package/src/primitives/list/index.ts +1 -0
- package/src/primitives/list/list-empty-state.css +10 -0
- package/src/primitives/list/list-item.css +93 -0
- package/src/primitives/list/list.css +6 -0
- package/src/primitives/number-input/NumberInput.tsx +235 -0
- package/src/primitives/number-input/index.ts +1 -0
- package/src/primitives/number-input/number-input.css +105 -0
- package/src/primitives/panel-loading/PanelLoading.tsx +29 -0
- package/src/primitives/panel-loading/index.ts +1 -0
- package/src/primitives/panel-loading/panel-loading.css +16 -0
- package/src/primitives/panel-surface/panel-surface.css +77 -0
- package/src/primitives/primitives.css +36 -0
- package/src/primitives/record-media-hero/RecordMediaHero.tsx +81 -0
- package/src/primitives/record-media-hero/index.ts +1 -0
- package/src/primitives/record-media-hero/record-media-hero.css +84 -0
- package/src/primitives/scroll-area/ScrollArea.tsx +200 -0
- package/src/primitives/scroll-area/index.ts +1 -0
- package/src/primitives/scroll-area/scroll-area-overlay.css +69 -0
- package/src/primitives/scroll-area-infinite-load/ScrollAreaInfiniteSentinel.tsx +22 -0
- package/src/primitives/scroll-area-infinite-load/index.ts +2 -0
- package/src/primitives/scroll-area-infinite-load/scroll-area-infinite-sentinel.css +6 -0
- package/src/primitives/scroll-area-infinite-load/useScrollAreaInfiniteLoad.ts +84 -0
- package/src/primitives/searchable-multi-select/SearchableMultiSelect.tsx +378 -0
- package/src/primitives/searchable-multi-select/index.ts +9 -0
- package/src/primitives/searchable-multi-select/overlay.ts +125 -0
- package/src/primitives/searchable-multi-select/searchable-multi-select.css +129 -0
- package/src/primitives/select/Select.tsx +21 -3
- package/src/primitives/select/overlay.ts +23 -4
- package/src/primitives/select/select.app.css +5 -2
- package/src/primitives/select/select.css +49 -12
- package/src/primitives/styles.css +3 -952
- package/src/primitives/tabbed-panels/TabbedPanels.tsx +68 -0
- package/src/primitives/tabbed-panels/index.ts +2 -0
- package/src/primitives/tabbed-panels/tabbed-panels.css +58 -0
- package/src/primitives/{TextArea.tsx → text-area/TextArea.tsx} +3 -2
- package/src/primitives/text-area/index.ts +1 -0
- package/src/primitives/{TextInput.tsx → text-input/TextInput.tsx} +3 -2
- package/src/primitives/text-input/index.ts +1 -0
- package/src/primitives/text-input/input.css +54 -0
- package/src/primitives/{Toolbar.tsx → toolbar/Toolbar.tsx} +1 -1
- package/src/primitives/toolbar/index.ts +1 -0
- package/src/primitives/visually-hidden/visually-hidden.css +11 -0
- package/src/primitives/{WorkbenchEditor.tsx → workbench-editor/WorkbenchEditor.tsx} +81 -43
- package/src/primitives/workbench-editor/button-group.css +10 -0
- package/src/primitives/workbench-editor/editor-tabs.css +201 -0
- package/src/primitives/workbench-editor/index.ts +1 -0
- package/src/primitives/workbench-editor/resizable-panels.css +53 -0
- package/src/primitives/workbench-editor/segmented-control.css +98 -0
- package/src/primitives/workbench-media-slot/WorkbenchMediaPlaceholder.tsx +25 -0
- package/src/primitives/workbench-media-slot/WorkbenchMediaSlot.tsx +60 -0
- package/src/primitives/workbench-media-slot/index.ts +2 -0
- package/src/primitives/workbench-media-slot/media-slot.css +72 -0
- package/src/primitives/workbench-thumbnail/WorkbenchThumbnail.tsx +38 -0
- package/src/primitives/workbench-thumbnail/index.ts +1 -0
- package/src/primitives/workbench-thumbnail/thumbnail.css +69 -0
- package/src/scrollbars.css +77 -2
- package/src/styles.css +13 -7735
- package/src/test-utils/workbenchMonacoMock.tsx +37 -0
- package/src/utils/dragMime.ts +89 -0
- package/src/utils/useWorkbenchMediaImage.ts +37 -0
- package/src/widget-asset/WidgetAssetEditor.tsx +9 -7
- package/src/widget-asset/WidgetAssetModeControls.tsx +1 -1
- package/src/widget-asset/WidgetAssetWorkbench.tsx +5 -6
- package/src/widget-studio/create-widget-studio-workspace-editor.tsx +1 -2
- package/src/widget-studio/index.ts +4 -1
- package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +27 -10
- package/src/widget-tree/WidgetAssetPalette.tsx +35 -7
- package/src/widget-tree/WidgetInspectorPanel.tsx +53 -3
- package/src/widget-tree/WidgetSourceEditor.tsx +90 -3
- package/src/widget-tree/WidgetTreeCanvasPreview.tsx +875 -0
- package/src/widget-tree/WidgetTreeLab.tsx +411 -83
- package/src/widget-tree/WidgetTreeModeControls.tsx +30 -1
- package/src/widget-tree/WidgetTreeSidePanel.tsx +24 -34
- package/src/widget-tree/WidgetTreeView.tsx +711 -11
- package/src/widget-tree/WidgetTreeWorkbench.tsx +59 -15
- package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +28 -10
- package/src/widget-tree/index.ts +22 -4
- package/src/widget-tree/widget-placement-asset-dnd.ts +35 -0
- package/src/widget-tree/widget-tree-document.ts +3 -9
- package/src/widget-tree/widget-tree-editor-state.ts +40 -0
- package/src/widget-tree/widget-tree-layout.ts +48 -3
- package/src/widget-tree/widget-tree-play-helpers.ts +69 -58
- package/src/workbench/auth/WorkbenchLoginView.tsx +4 -6
- package/src/workbench/auth/auth-flows.css +440 -0
- package/src/workbench/auth/auth.css +3 -0
- package/src/workbench/auth/profile-modals.css +115 -0
- package/src/workbench/bootstrap/WorkbenchBootstrapGate.tsx +45 -0
- package/src/workbench/bootstrap/WorkbenchBootstrapView.tsx +100 -0
- package/src/workbench/bootstrap/index.ts +12 -0
- package/src/workbench/bootstrap/useWorkbenchBootstrap.ts +130 -0
- package/src/workbench/chat/ChatCommandProposalCard.tsx +115 -0
- package/src/workbench/chat/ChatComposer.tsx +32 -34
- package/src/workbench/chat/ChatConversationBar.tsx +134 -0
- package/src/workbench/chat/ChatHistoryMenu.tsx +171 -0
- package/src/workbench/chat/ChatHistoryMenuRow.tsx +74 -0
- package/src/workbench/chat/ChatMessageCollapsible.tsx +119 -0
- package/src/workbench/chat/ChatMessageItem.tsx +351 -19
- package/src/workbench/chat/ChatMessageList.tsx +109 -24
- package/src/workbench/chat/ChatPanel.tsx +141 -19
- package/src/workbench/chat/ChatPhasedRunProgress.tsx +275 -0
- package/src/workbench/chat/ChatRenameDialog.tsx +77 -0
- package/src/workbench/chat/chat-conversation.css +273 -0
- package/src/workbench/chat/chat-ui.css +1132 -0
- package/src/workbench/chat/chat.css +3 -0
- package/src/workbench/chat/chatConversation.ts +46 -0
- package/src/workbench/chat/chatHistoryRowMenuItems.ts +29 -0
- package/src/workbench/chat/chatMessageMeta.tsx +252 -0
- package/src/workbench/chat/chatScroll.ts +22 -0
- package/src/workbench/chat/index.ts +48 -1
- package/src/workbench/chat/slashCommand.ts +5 -7
- package/src/workbench/chat/types.ts +35 -0
- package/src/workbench/chat/useCancelRuntimeOnUnmount.ts +60 -0
- package/src/workbench/chat/useChatPrependPagination.ts +233 -0
- package/src/workbench/chat/useChatRuntimeState.ts +3 -15
- package/src/workbench/chat/useSlashCommandSuggest.ts +77 -24
- package/src/workbench/chrome/WorkbenchModalPortal.tsx +52 -0
- package/src/workbench/chrome/WorkbenchPlatformContext.tsx +31 -0
- package/src/workbench/chrome/index.css +6 -0
- package/src/workbench/chrome/workbench-chrome.css +4 -0
- package/src/workbench/chrome/workbench-desktop-titlebar.css +60 -0
- package/src/workbench/chrome/workbench-host.css +85 -0
- package/src/workbench/chrome/workbench-layout-regions.css +42 -0
- package/src/workbench/chrome/workbench-platform-chrome.css +142 -0
- package/src/workbench/chrome/workbench-shell-titlebar.css +124 -0
- package/src/workbench/chrome/workbenchModalViewState.ts +52 -0
- package/src/workbench/chrome/workbenchOverlaysContext.tsx +21 -0
- package/src/workbench/chrome/workbenchPlatformChrome.ts +40 -0
- package/src/workbench/command-palette/command-palette.css +156 -0
- package/src/workbench/commands/CommandGroupShell.tsx +131 -0
- package/src/workbench/commands/CommandList.tsx +167 -0
- package/src/workbench/commands/CommandPalette.tsx +391 -0
- package/src/workbench/{ConfirmationFlow.tsx → commands/ConfirmationFlow.tsx} +6 -8
- package/src/workbench/{ShortcutCommandBridge.tsx → commands/ShortcutCommandBridge.tsx} +1 -4
- package/src/workbench/commands/command-execution-policy.ts +61 -0
- package/src/workbench/commands/command-model.ts +279 -0
- package/src/workbench/{commands.ts → commands/commands.ts} +63 -7
- package/src/workbench/commands/workbenchContextMenu.ts +18 -0
- package/src/workbench/editor/WorkbenchEditorTabs.tsx +52 -0
- package/src/workbench/editor/editor-tabs-dnd.ts +162 -0
- package/src/workbench/editor/editorTabContextMenu.ts +111 -0
- package/src/workbench/editor/useEditorTabsStripDnd.ts +262 -0
- package/src/workbench/editor/useWorkbenchEditorTabContextMenu.tsx +66 -0
- package/src/workbench/editor-tabs/index.ts +22 -0
- package/src/workbench/index.ts +288 -37
- package/src/workbench/management/AccountManagementPanel.tsx +82 -0
- package/src/workbench/management/CommandInspectorPanel.tsx +127 -0
- package/src/workbench/management/CommandManagementPanel.tsx +129 -0
- package/src/workbench/management/CommandManagementSidebar.tsx +318 -0
- package/src/workbench/management/ExtensionManagementPanel.tsx +527 -0
- package/src/workbench/management/ExtensionManagementSidebar.tsx +509 -0
- package/src/workbench/management/IntegrationCommandActions.tsx +78 -0
- package/src/workbench/management/IntegrationSettingsSurface.tsx +290 -0
- package/src/workbench/management/IntegrationsShell.tsx +53 -0
- package/src/workbench/management/KeybindingCaptureField.tsx +142 -0
- package/src/workbench/management/KeybindingManagementPanel.tsx +120 -0
- package/src/workbench/management/LibraryCatalogPickerDialog.tsx +208 -0
- package/src/workbench/management/LibraryFacetFilterDialog.tsx +62 -0
- package/src/workbench/management/ManagementCard.tsx +89 -0
- package/src/workbench/management/ManagementFilterChips.tsx +41 -0
- package/src/workbench/management/ManagementGroup.tsx +56 -0
- package/src/workbench/management/ManagementPanelControls.tsx +43 -0
- package/src/workbench/management/ManagementPanelFrame.tsx +109 -0
- package/src/workbench/management/WorkbenchDialogFrame.tsx +148 -0
- package/src/workbench/management/WorkbenchNotice.tsx +211 -0
- package/src/workbench/management/build-command-management-groups.ts +157 -0
- package/src/workbench/management/command-inspector-uri.ts +26 -0
- package/src/workbench/management/extension-category-display.ts +42 -0
- package/src/workbench/management/extension-install-approval.ts +72 -0
- package/src/workbench/management/format-command-run-state.ts +19 -0
- package/src/workbench/management/index.ts +137 -0
- package/src/workbench/management/integration-command-action.ts +25 -0
- package/src/workbench/management/library-catalog-picker-dialog.css +56 -0
- package/src/workbench/management/library-facet-filter-dialog.css +8 -0
- package/src/workbench/management/management-panel.css +444 -0
- package/src/workbench/management/management.css +4 -0
- package/src/workbench/management/types.ts +139 -0
- package/src/workbench/{MarkdownPreview.tsx → markdown/MarkdownPreview.tsx} +26 -15
- package/src/workbench/markdown/markdownRemarkPlugins.ts +12 -0
- package/src/workbench/markdown/sanitizeMarkdownHref.ts +29 -0
- package/src/workbench/schema/index.ts +0 -1
- package/src/workbench/settings/NavigationPanel.tsx +41 -2
- package/src/workbench/settings/SchemaForm.tsx +20 -7
- package/src/workbench/settings/SectionTabPanel.tsx +172 -0
- package/src/workbench/settings/SectionedPanel.tsx +40 -286
- package/src/workbench/settings/StructuredDataForm.tsx +106 -26
- package/src/workbench/settings/StructuredDataSchemaPanel.tsx +345 -93
- package/src/workbench/settings/StructuredDataTableView.tsx +2 -2
- package/src/workbench/settings/WorkbenchPanelRegion.tsx +1 -1
- package/src/workbench/settings/WorkbenchSettingsModal.tsx +116 -62
- package/src/workbench/settings/WorkbenchSettingsNav.tsx +3 -3
- package/src/workbench/settings/extensionSettingsForm.ts +34 -0
- package/src/workbench/settings/index.ts +36 -1
- package/src/workbench/settings/navigation-panel.css +59 -0
- package/src/workbench/settings/panel-region.css +3 -2
- package/src/workbench/settings/schema-form.css +36 -0
- package/src/workbench/settings/schemaFormSettingSpec.ts +177 -0
- package/src/workbench/settings/schemaFormSettingsCategory.tsx +21 -0
- package/src/workbench/settings/section-tab-panel.css +157 -0
- package/src/workbench/settings/sectionScrollSpyDom.ts +139 -0
- package/src/workbench/settings/sectioned-panel.css +162 -0
- package/src/workbench/settings/sectionedPanelScrollSpy.ts +158 -28
- package/src/workbench/settings/settings-responsive.css +58 -0
- package/src/workbench/settings/settings.css +11 -0
- package/src/workbench/settings/settingsCommit.tsx +55 -0
- package/src/workbench/settings/structured-data-form.css +114 -0
- package/src/workbench/settings/structured-data-schema-panel.css +33 -19
- package/src/workbench/settings/structuredDataFormModel.ts +140 -0
- package/src/workbench/settings/structuredDataSchema.ts +111 -658
- package/src/workbench/settings/structuredDataSchemaDate.ts +197 -0
- package/src/workbench/settings/structuredDataSchemaField.ts +105 -0
- package/src/workbench/settings/structuredDataSchemaSection.ts +74 -0
- package/src/workbench/settings/structuredDataSchemaTable.ts +120 -0
- package/src/workbench/settings/structuredDataSchemaTypes.ts +308 -0
- package/src/workbench/settings/structuredDataSchemaValidation.ts +166 -0
- package/src/workbench/settings/useSectionScrollSpy.ts +420 -0
- package/src/workbench/settings/workbench-settings-modal.css +273 -0
- package/src/workbench/shell/ActivityBar.tsx +159 -0
- package/src/workbench/{ArtifactShell.tsx → shell/ArtifactShell.tsx} +30 -30
- package/src/workbench/shell/SplitView.tsx +485 -0
- package/src/workbench/{StatusBar.tsx → shell/StatusBar.tsx} +10 -8
- package/src/workbench/{StructuredArtifactEditor.tsx → shell/StructuredArtifactEditor.tsx} +9 -9
- package/src/workbench/{Timeline.tsx → shell/Timeline.tsx} +19 -24
- package/src/workbench/shell/WorkbenchCanvasShell.defaults.ts +106 -0
- package/src/workbench/shell/WorkbenchCanvasShell.model.ts +46 -0
- package/src/workbench/{WorkbenchCanvasShell.tsx → shell/WorkbenchCanvasShell.tsx} +34 -148
- package/src/workbench/shell/WorkbenchDesktopTitleBar.tsx +126 -0
- package/src/workbench/shell/WorkbenchShell.tsx +192 -0
- package/src/workbench/shell/WorkbenchShellTitleBarLayoutControls.tsx +80 -0
- package/src/workbench/shell/WorkbenchStandaloneShell.tsx +604 -0
- package/src/workbench/shell/WorkbenchViewEditor.tsx +75 -0
- package/src/workbench/shell/WorkbenchViewSidebar.tsx +85 -0
- package/src/workbench/shell/WorkbenchWindowChromeControls.tsx +293 -0
- package/src/workbench/shell/activity-bar.css +245 -0
- package/src/workbench/shell/activityBarOrder.ts +98 -0
- package/src/workbench/shell/appearanceLabels.ts +28 -0
- package/src/workbench/shell/confirmation-flow.css +87 -0
- package/src/workbench/shell/hardReset.ts +64 -0
- package/src/workbench/shell/index.css +5 -0
- package/src/workbench/shell/shell.ts +152 -0
- package/src/workbench/shell/shellPresets.ts +36 -0
- package/src/workbench/{shellState.ts → shell/shellState.ts} +16 -23
- package/src/workbench/shell/shellViewModel.ts +160 -0
- package/src/workbench/shell/sidebarViewPlacementDnd.ts +61 -0
- package/src/workbench/shell/split-view.css +188 -0
- package/src/workbench/{standalone.ts → shell/standalone.ts} +11 -11
- package/src/workbench/shell/status-bar.css +141 -0
- package/src/workbench/{status.ts → shell/status.ts} +10 -6
- package/src/workbench/shell/useDeferredWorkbenchMount.ts +71 -0
- package/src/workbench/shell/useWorkbenchAppearanceDocumentSync.tsx +17 -0
- package/src/workbench/shell/useWorkbenchSidebarActionBarDnd.ts +227 -0
- package/src/workbench/shell/useWorkbenchSidebarLayout.tsx +232 -0
- package/src/workbench/shell/useWorkbenchSidebarViewPlacementDropZone.ts +194 -0
- package/src/workbench/shell/useWorkbenchStandaloneShellStateSync.tsx +112 -0
- package/src/workbench/shell/workbenchSidebarLayoutContext.ts +46 -0
- package/src/workbench/shell/workbenchStandaloneShellReactContext.tsx +80 -0
- package/src/workbench/shell/workbenchViewRouteState.ts +151 -0
- package/src/workbench/theme/WorkbenchThemeProvider.tsx +142 -0
- package/src/workbench/{theme.ts → theme/theme.ts} +9 -3
- package/src/workbench/theme/themePresets.ts +191 -0
- package/src/workbench/views/action-list.css +144 -0
- package/src/workbench/views/artifact-preview.css +184 -0
- package/src/workbench/views/command-inspector.css +98 -0
- package/src/workbench/views/command-list.css +356 -0
- package/src/workbench/views/commands-sidebar.css +51 -0
- package/src/workbench/views/extensions-sidebar.css +175 -0
- package/src/workbench/views/multi-provider-explorer.css +182 -0
- package/src/workbench/views/search.css +10 -0
- package/src/workbench/views/timeline.css +239 -0
- package/src/workbench/views/view-hosts.css +37 -0
- package/src/workbench/views/view-sidebar.css +21 -0
- package/src/workbench/views/views.css +12 -0
- package/src/workbench/widgets/widget-tree.css +598 -0
- package/src/workbench/widgets/widgets.css +2 -0
- package/src/workbench/workspace/WorkspaceDraftsContext.tsx +59 -71
- package/src/workbench/workspace/WorkspaceEditor.tsx +27 -123
- package/src/workbench/workspace/WorkspaceEditorPanel.tsx +68 -9
- package/src/workbench/workspace/WorkspaceExplorer.tsx +149 -51
- package/src/workbench/workspace/WorkspaceExplorerPanel.tsx +73 -0
- package/src/workbench/workspace/WorkspaceFileIcon.tsx +4 -160
- package/src/workbench/workspace/WorkspacePathLabel.tsx +42 -0
- package/src/workbench/workspace/WorkspaceSearchPanel.tsx +18 -15
- package/src/workbench/workspace/WorkspaceSearchResults.tsx +6 -2
- package/src/workbench/workspace/build-workspace-explorer-nodes.ts +44 -0
- package/src/workbench/workspace/createVirtualWorkspaceExplorerPort.ts +141 -0
- package/src/workbench/workspace/explorer-tree-style.ts +18 -0
- package/src/workbench/workspace/index.ts +45 -32
- package/src/workbench/workspace/json-config-workbench.css +57 -0
- package/src/workbench/workspace/monaco-panel.css +71 -0
- package/src/workbench/workspace/path.ts +2 -0
- package/src/workbench/workspace/useWorkspaceExplorerController.ts +490 -0
- package/src/workbench/workspace/workspace-editor.css +235 -0
- package/src/workbench/workspace/workspace-explorer-panel.css +33 -0
- package/src/workbench/workspace/workspace.css +5 -0
- package/src/workbench/workspace/workspaceExplorerController.ts +193 -0
- package/src/workbench/workspace/workspaceJsonDiagnostics.ts +8 -7
- package/src/workbench-menu-surfaces.css +57 -0
- package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +0 -126
- package/src/layout/SideBarViewFrame.tsx +0 -367
- package/src/primitives/Checkbox.tsx +0 -21
- package/src/primitives/NumberInput.tsx +0 -38
- package/src/primitives/ScrollArea.tsx +0 -42
- package/src/primitives/Select.tsx +0 -1
- package/src/primitives/StatusBar.tsx +0 -46
- package/src/primitives/WorkbenchChrome.tsx +0 -424
- package/src/workbench/ActivityBar.tsx +0 -52
- package/src/workbench/CommandPalette.tsx +0 -819
- package/src/workbench/SplitView.tsx +0 -136
- package/src/workbench/WorkbenchShell.tsx +0 -74
- package/src/workbench/WorkbenchStandaloneShell.tsx +0 -318
- package/src/workbench/shell.ts +0 -15
- package/src/workbench/workspace/MultiProviderExplorer.tsx +0 -625
- /package/src/workbench/{keyboard.ts → commands/keyboard.ts} +0 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import type { CommandMenuItem, ResolvedCommandMenuCommandItem } from '@workbench-kit/platform';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getWorkbenchStatusLabel,
|
|
5
|
+
isWorkbenchStatusDisabled,
|
|
6
|
+
type WorkbenchStatus,
|
|
7
|
+
} from '../shell/status';
|
|
8
|
+
|
|
9
|
+
export type WorkbenchCommandStatus = WorkbenchStatus;
|
|
10
|
+
|
|
11
|
+
export interface WorkbenchCommandExecution {
|
|
12
|
+
kind: 'agent' | 'local' | 'remote' | 'composite' | (string & {});
|
|
13
|
+
label?: string | undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type WorkbenchCommandFeedback = 'none' | 'status' | 'timeline';
|
|
17
|
+
export type WorkbenchCommandOutput = 'none' | 'message' | 'event' | 'artifact';
|
|
18
|
+
export type WorkbenchCommandSideEffect = 'none' | 'workspace-write' | 'external-write';
|
|
19
|
+
export type WorkbenchCommandExecutionPolicy = 'auto-allow' | 'approval-required' | 'auto-deny';
|
|
20
|
+
export type WorkbenchCommandRunSource = 'grouped-list' | 'list' | 'palette' | 'suggest';
|
|
21
|
+
export type WorkbenchCommandGroupBy =
|
|
22
|
+
'category' | 'danger' | 'execution' | 'feedback' | 'keyword' | 'output' | 'sideEffect' | 'status';
|
|
23
|
+
|
|
24
|
+
export interface WorkbenchCommandDescriptor {
|
|
25
|
+
category?: string | undefined;
|
|
26
|
+
danger?: boolean | undefined;
|
|
27
|
+
description?: string | undefined;
|
|
28
|
+
disabled?: boolean | undefined;
|
|
29
|
+
disabledReason?: string | undefined;
|
|
30
|
+
execution?: WorkbenchCommandExecution | undefined;
|
|
31
|
+
executionPolicy?: WorkbenchCommandExecutionPolicy | undefined;
|
|
32
|
+
feedback?: WorkbenchCommandFeedback | undefined;
|
|
33
|
+
icon?: string | undefined;
|
|
34
|
+
id: string;
|
|
35
|
+
keywords?: readonly string[] | undefined;
|
|
36
|
+
label: string;
|
|
37
|
+
metadata?: Record<string, unknown> | undefined;
|
|
38
|
+
output?: WorkbenchCommandOutput | undefined;
|
|
39
|
+
shortcut?: string | undefined;
|
|
40
|
+
sideEffect?: WorkbenchCommandSideEffect | undefined;
|
|
41
|
+
status?: WorkbenchCommandStatus | undefined;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface WorkbenchCommandRunContext {
|
|
45
|
+
groupId?: string | undefined;
|
|
46
|
+
groupLabel?: string | undefined;
|
|
47
|
+
index: number;
|
|
48
|
+
query: string;
|
|
49
|
+
source: WorkbenchCommandRunSource;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface WorkbenchCommandFilterInput {
|
|
53
|
+
commands: readonly WorkbenchCommandDescriptor[];
|
|
54
|
+
limit?: number | undefined;
|
|
55
|
+
query?: string | undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface WorkbenchCommandNavigationInput {
|
|
59
|
+
commands: readonly WorkbenchCommandDescriptor[];
|
|
60
|
+
currentIndex: number;
|
|
61
|
+
direction: 'next' | 'previous';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface WorkbenchCommandGroup {
|
|
65
|
+
commands: readonly WorkbenchCommandDescriptor[];
|
|
66
|
+
id: string;
|
|
67
|
+
label: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface WorkbenchCommandGroupingInput {
|
|
71
|
+
commands: readonly WorkbenchCommandDescriptor[];
|
|
72
|
+
fallbackGroupLabel?: string | undefined;
|
|
73
|
+
groupBy?: WorkbenchCommandGroupBy | undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type WorkbenchCommandDescriptorOverrides = Partial<
|
|
77
|
+
Omit<WorkbenchCommandDescriptor, 'danger' | 'disabled' | 'icon' | 'id' | 'label' | 'shortcut'>
|
|
78
|
+
>;
|
|
79
|
+
|
|
80
|
+
const commandExecutionLabels: Record<string, string> = {
|
|
81
|
+
agent: 'Agent',
|
|
82
|
+
composite: 'Composite',
|
|
83
|
+
local: 'Local',
|
|
84
|
+
remote: 'Remote',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const commandFeedbackLabels: Record<WorkbenchCommandFeedback, string> = {
|
|
88
|
+
none: 'No feedback',
|
|
89
|
+
status: 'Status',
|
|
90
|
+
timeline: 'Timeline',
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const commandOutputLabels: Record<WorkbenchCommandOutput, string> = {
|
|
94
|
+
artifact: 'Artifact',
|
|
95
|
+
event: 'Event',
|
|
96
|
+
message: 'Message',
|
|
97
|
+
none: 'No output',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const commandSideEffectLabels: Record<WorkbenchCommandSideEffect, string> = {
|
|
101
|
+
'external-write': 'External write',
|
|
102
|
+
none: 'No side effect',
|
|
103
|
+
'workspace-write': 'Workspace write',
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
function normalizedSearchText(value: string) {
|
|
107
|
+
return value.trim().toLocaleLowerCase();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function commandSearchText(command: WorkbenchCommandDescriptor) {
|
|
111
|
+
return normalizedSearchText(
|
|
112
|
+
[
|
|
113
|
+
command.id,
|
|
114
|
+
command.label,
|
|
115
|
+
command.description,
|
|
116
|
+
command.category,
|
|
117
|
+
command.shortcut,
|
|
118
|
+
...(command.keywords ?? []),
|
|
119
|
+
]
|
|
120
|
+
.filter(Boolean)
|
|
121
|
+
.join(' '),
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function normalizeWorkbenchCommandQuery(query = '') {
|
|
126
|
+
const trimmed = query.trimStart();
|
|
127
|
+
|
|
128
|
+
return trimmed.startsWith('>') ? trimmed.slice(1).trimStart() : query;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function getWorkbenchCommandStatusLabel(status: WorkbenchCommandStatus) {
|
|
132
|
+
return getWorkbenchStatusLabel(status);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function getWorkbenchCommandExecutionLabel(execution: WorkbenchCommandExecution) {
|
|
136
|
+
return execution.label ?? commandExecutionLabels[execution.kind] ?? execution.kind;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function isWorkbenchCommandRunnable(command: WorkbenchCommandDescriptor) {
|
|
140
|
+
return !(command.disabled || (command.status && isWorkbenchStatusDisabled(command.status)));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function normalizeWorkbenchCommandGroupId(label: string) {
|
|
144
|
+
const normalized = normalizedSearchText(label)
|
|
145
|
+
.replace(/[^\p{L}\p{N}]+/gu, '-')
|
|
146
|
+
.replace(/^-+|-+$/g, '');
|
|
147
|
+
|
|
148
|
+
return normalized || 'group';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function getWorkbenchCommandGroupLabels({
|
|
152
|
+
command,
|
|
153
|
+
fallbackGroupLabel,
|
|
154
|
+
groupBy = 'category',
|
|
155
|
+
}: {
|
|
156
|
+
command: WorkbenchCommandDescriptor;
|
|
157
|
+
fallbackGroupLabel: string;
|
|
158
|
+
groupBy?: WorkbenchCommandGroupBy | undefined;
|
|
159
|
+
}) {
|
|
160
|
+
if (groupBy === 'keyword') {
|
|
161
|
+
return command.keywords?.length ? [...command.keywords] : [fallbackGroupLabel];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (groupBy === 'category') return [command.category ?? fallbackGroupLabel];
|
|
165
|
+
if (groupBy === 'danger') return [command.danger ? 'Danger' : 'Default'];
|
|
166
|
+
if (groupBy === 'execution') {
|
|
167
|
+
return [
|
|
168
|
+
command.execution ? getWorkbenchCommandExecutionLabel(command.execution) : fallbackGroupLabel,
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
if (groupBy === 'feedback')
|
|
172
|
+
return [command.feedback ? commandFeedbackLabels[command.feedback] : fallbackGroupLabel];
|
|
173
|
+
if (groupBy === 'output')
|
|
174
|
+
return [command.output ? commandOutputLabels[command.output] : fallbackGroupLabel];
|
|
175
|
+
if (groupBy === 'sideEffect') {
|
|
176
|
+
return [command.sideEffect ? commandSideEffectLabels[command.sideEffect] : fallbackGroupLabel];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const status = command.status ?? (command.disabled ? 'disabled' : undefined);
|
|
180
|
+
return [status ? getWorkbenchCommandStatusLabel(status) : fallbackGroupLabel];
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function groupWorkbenchCommands({
|
|
184
|
+
commands,
|
|
185
|
+
fallbackGroupLabel = 'Other',
|
|
186
|
+
groupBy = 'category',
|
|
187
|
+
}: WorkbenchCommandGroupingInput): WorkbenchCommandGroup[] {
|
|
188
|
+
const groups = new Map<string, { commands: WorkbenchCommandDescriptor[]; label: string }>();
|
|
189
|
+
|
|
190
|
+
commands.forEach((command) => {
|
|
191
|
+
getWorkbenchCommandGroupLabels({ command, fallbackGroupLabel, groupBy }).forEach((label) => {
|
|
192
|
+
const id = normalizeWorkbenchCommandGroupId(`${groupBy}-${label}`);
|
|
193
|
+
const group = groups.get(id) ?? { commands: [], label };
|
|
194
|
+
|
|
195
|
+
group.commands.push(command);
|
|
196
|
+
groups.set(id, group);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return Array.from(groups, ([id, group]) => ({
|
|
201
|
+
commands: group.commands,
|
|
202
|
+
id,
|
|
203
|
+
label: group.label,
|
|
204
|
+
}));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function filterWorkbenchCommands({
|
|
208
|
+
commands,
|
|
209
|
+
limit,
|
|
210
|
+
query = '',
|
|
211
|
+
}: WorkbenchCommandFilterInput) {
|
|
212
|
+
const tokens = normalizedSearchText(normalizeWorkbenchCommandQuery(query))
|
|
213
|
+
.split(/\s+/)
|
|
214
|
+
.filter(Boolean);
|
|
215
|
+
const filtered = tokens.length
|
|
216
|
+
? commands.filter((command) => {
|
|
217
|
+
const searchText = commandSearchText(command);
|
|
218
|
+
return tokens.every((token) => searchText.includes(token));
|
|
219
|
+
})
|
|
220
|
+
: [...commands];
|
|
221
|
+
|
|
222
|
+
return typeof limit === 'number' ? filtered.slice(0, limit) : filtered;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function getNextWorkbenchCommandIndex({
|
|
226
|
+
commands,
|
|
227
|
+
currentIndex,
|
|
228
|
+
direction,
|
|
229
|
+
}: WorkbenchCommandNavigationInput) {
|
|
230
|
+
if (commands.length === 0) return -1;
|
|
231
|
+
|
|
232
|
+
const step = direction === 'next' ? 1 : -1;
|
|
233
|
+
const startIndex =
|
|
234
|
+
currentIndex >= 0 && currentIndex < commands.length
|
|
235
|
+
? currentIndex
|
|
236
|
+
: direction === 'next'
|
|
237
|
+
? -1
|
|
238
|
+
: 0;
|
|
239
|
+
|
|
240
|
+
for (let offset = 1; offset <= commands.length; offset += 1) {
|
|
241
|
+
const nextIndex = (startIndex + step * offset + commands.length) % commands.length;
|
|
242
|
+
const command = commands[nextIndex];
|
|
243
|
+
if (command && isWorkbenchCommandRunnable(command)) return nextIndex;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return -1;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function commandMenuItemToWorkbenchCommandDescriptor(
|
|
250
|
+
item: ResolvedCommandMenuCommandItem,
|
|
251
|
+
overrides: WorkbenchCommandDescriptorOverrides = {},
|
|
252
|
+
): WorkbenchCommandDescriptor {
|
|
253
|
+
const metadata = {
|
|
254
|
+
menuItemId: item.id,
|
|
255
|
+
...overrides.metadata,
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
...overrides,
|
|
260
|
+
danger: item.danger,
|
|
261
|
+
disabled: item.disabled,
|
|
262
|
+
icon: item.icon,
|
|
263
|
+
id: item.commandId,
|
|
264
|
+
label: item.label,
|
|
265
|
+
metadata,
|
|
266
|
+
shortcut: item.shortcut,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export function commandMenuItemsToWorkbenchCommandDescriptors(
|
|
271
|
+
items: readonly CommandMenuItem[],
|
|
272
|
+
overridesByCommandId: Record<string, WorkbenchCommandDescriptorOverrides> = {},
|
|
273
|
+
) {
|
|
274
|
+
return items.flatMap((item) =>
|
|
275
|
+
item.type === 'command'
|
|
276
|
+
? [commandMenuItemToWorkbenchCommandDescriptor(item, overridesByCommandId[item.commandId])]
|
|
277
|
+
: [],
|
|
278
|
+
);
|
|
279
|
+
}
|
|
@@ -10,13 +10,16 @@ import {
|
|
|
10
10
|
type CommandValue,
|
|
11
11
|
} from '@workbench-kit/platform';
|
|
12
12
|
|
|
13
|
-
import type { ContextMenuItem } from '
|
|
13
|
+
import type { ContextMenuItem } from '../../overlay/ContextMenu';
|
|
14
14
|
|
|
15
15
|
export const WORKBENCH_OPEN_SETTINGS_COMMAND_ID = 'workbench.openSettings';
|
|
16
16
|
export const WORKBENCH_TOGGLE_PRIMARY_SIDEBAR_COMMAND_ID = 'workbench.togglePrimarySidebar';
|
|
17
17
|
export const WORKBENCH_EDITOR_SAVE_COMMAND_ID = 'editor.save';
|
|
18
18
|
export const WORKBENCH_EDITOR_DISCARD_CHANGES_COMMAND_ID = 'editor.discardChanges';
|
|
19
19
|
export const WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID = 'editor.copyPath';
|
|
20
|
+
export const WORKBENCH_EDITOR_TOGGLE_PINNED_COMMAND_ID = 'editor.togglePinned';
|
|
21
|
+
export const WORKBENCH_EDITOR_SPLIT_RIGHT_COMMAND_ID = 'editor.splitRight';
|
|
22
|
+
export const WORKBENCH_EDITOR_SPLIT_DOWN_COMMAND_ID = 'editor.splitDown';
|
|
20
23
|
export const WORKBENCH_EDITOR_CLOSE_COMMAND_ID = 'editor.close';
|
|
21
24
|
export const WORKBENCH_EDITOR_CLOSE_OTHERS_COMMAND_ID = 'editor.closeOthers';
|
|
22
25
|
export const WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID = 'editor.closeAll';
|
|
@@ -100,8 +103,7 @@ export interface WorkbenchShellCommandPresetOptions<TActivityId extends string =
|
|
|
100
103
|
settingsLabel?: string | undefined;
|
|
101
104
|
sidebarIcon?: string | undefined;
|
|
102
105
|
commandOverrides?:
|
|
103
|
-
|
|
104
|
-
| undefined;
|
|
106
|
+
WorkbenchCommandOverrides<WorkbenchShellCommandContext<TActivityId>> | undefined;
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
export interface WorkbenchEditorCommandContext {
|
|
@@ -112,6 +114,9 @@ export interface WorkbenchEditorCommandContext {
|
|
|
112
114
|
canDeletePath: boolean;
|
|
113
115
|
canDiscardFile: boolean;
|
|
114
116
|
canSaveFile: boolean;
|
|
117
|
+
canSplitDown: boolean;
|
|
118
|
+
canSplitRight: boolean;
|
|
119
|
+
canTogglePinned: boolean;
|
|
115
120
|
closeAll: () => void;
|
|
116
121
|
closeOthers: () => void;
|
|
117
122
|
closePath: () => void;
|
|
@@ -122,7 +127,11 @@ export interface WorkbenchEditorCommandContext {
|
|
|
122
127
|
hasMultipleOpenFiles: boolean;
|
|
123
128
|
hasOpenFiles: boolean;
|
|
124
129
|
hasUnsavedChanges: boolean;
|
|
130
|
+
isPinned: boolean;
|
|
125
131
|
saveFile: () => void;
|
|
132
|
+
splitDown: () => void;
|
|
133
|
+
splitRight: () => void;
|
|
134
|
+
togglePinned: () => void;
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
export interface WorkbenchWorkspaceCommandContext {
|
|
@@ -177,6 +186,7 @@ export function createWorkbenchShellCommands<TActivityId extends string>({
|
|
|
177
186
|
label: ({ isPrimarySidebarVisible }) =>
|
|
178
187
|
isPrimarySidebarVisible ? 'Hide primary sidebar' : 'Show primary sidebar',
|
|
179
188
|
run: ({ togglePrimarySidebar }) => togglePrimarySidebar(),
|
|
189
|
+
title: 'Toggle primary sidebar',
|
|
180
190
|
});
|
|
181
191
|
}
|
|
182
192
|
|
|
@@ -186,6 +196,7 @@ export function createWorkbenchShellCommands<TActivityId extends string>({
|
|
|
186
196
|
icon: settingsIcon,
|
|
187
197
|
label: settingsLabel,
|
|
188
198
|
run: ({ openSettings }) => openSettings(),
|
|
199
|
+
title: settingsLabel,
|
|
189
200
|
});
|
|
190
201
|
}
|
|
191
202
|
|
|
@@ -264,6 +275,30 @@ export function createWorkbenchEditorCommands({
|
|
|
264
275
|
label: 'Copy path',
|
|
265
276
|
run: ({ copyPath }) => copyPath(),
|
|
266
277
|
},
|
|
278
|
+
{
|
|
279
|
+
id: WORKBENCH_EDITOR_TOGGLE_PINNED_COMMAND_ID,
|
|
280
|
+
icon: 'codicon-pinned',
|
|
281
|
+
isEnabled: ({ canTogglePinned, filePath }) => Boolean(filePath && canTogglePinned),
|
|
282
|
+
isVisible: ({ canTogglePinned, filePath }) => Boolean(filePath && canTogglePinned),
|
|
283
|
+
label: ({ isPinned }) => (isPinned ? 'Unpin' : 'Pin'),
|
|
284
|
+
run: ({ togglePinned }) => togglePinned(),
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: WORKBENCH_EDITOR_SPLIT_RIGHT_COMMAND_ID,
|
|
288
|
+
icon: 'codicon-split-horizontal',
|
|
289
|
+
isEnabled: ({ canSplitRight, filePath }) => Boolean(filePath && canSplitRight),
|
|
290
|
+
isVisible: ({ canSplitRight, filePath }) => Boolean(filePath && canSplitRight),
|
|
291
|
+
label: 'Split Right',
|
|
292
|
+
run: ({ splitRight }) => splitRight(),
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: WORKBENCH_EDITOR_SPLIT_DOWN_COMMAND_ID,
|
|
296
|
+
icon: 'codicon-split-vertical',
|
|
297
|
+
isEnabled: ({ canSplitDown, filePath }) => Boolean(filePath && canSplitDown),
|
|
298
|
+
isVisible: ({ canSplitDown, filePath }) => Boolean(filePath && canSplitDown),
|
|
299
|
+
label: 'Split Down',
|
|
300
|
+
run: ({ splitDown }) => splitDown(),
|
|
301
|
+
},
|
|
267
302
|
{
|
|
268
303
|
id: WORKBENCH_EDITOR_CLOSE_COMMAND_ID,
|
|
269
304
|
icon: 'codicon-close',
|
|
@@ -309,10 +344,35 @@ export function createWorkbenchEditorTabListMenuEntries(): CommandMenuEntry<Work
|
|
|
309
344
|
|
|
310
345
|
export function createWorkbenchEditorTabMenuEntries(): CommandMenuEntry<WorkbenchEditorCommandContext>[] {
|
|
311
346
|
return [
|
|
347
|
+
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_TOGGLE_PINNED_COMMAND_ID, {
|
|
348
|
+
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
349
|
+
}),
|
|
350
|
+
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_SPLIT_RIGHT_COMMAND_ID, {
|
|
351
|
+
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
352
|
+
}),
|
|
353
|
+
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_SPLIT_DOWN_COMMAND_ID, {
|
|
354
|
+
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
355
|
+
}),
|
|
356
|
+
commandMenuSeparator('tab-layout-separator'),
|
|
312
357
|
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_COPY_PATH_COMMAND_ID, {
|
|
313
358
|
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
314
359
|
}),
|
|
315
360
|
commandMenuSeparator('tab-file-separator'),
|
|
361
|
+
...createWorkbenchStandaloneEditorTabMenuEntries(),
|
|
362
|
+
commandMenuSeparator('tab-danger-separator'),
|
|
363
|
+
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_DELETE_COMMAND_ID, {
|
|
364
|
+
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
365
|
+
}),
|
|
366
|
+
];
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Close-only tab menu entries for chrome hosts that own tab state without pin,
|
|
371
|
+
* split, copy-path, or delete actions (for example `WorkbenchStandaloneShell`
|
|
372
|
+
* secondary areas using `WorkbenchEditorTabs`).
|
|
373
|
+
*/
|
|
374
|
+
export function createWorkbenchStandaloneEditorTabMenuEntries(): CommandMenuEntry<WorkbenchEditorCommandContext>[] {
|
|
375
|
+
return [
|
|
316
376
|
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_COMMAND_ID, {
|
|
317
377
|
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
318
378
|
}),
|
|
@@ -322,10 +382,6 @@ export function createWorkbenchEditorTabMenuEntries(): CommandMenuEntry<Workbenc
|
|
|
322
382
|
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_CLOSE_ALL_COMMAND_ID, {
|
|
323
383
|
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
324
384
|
}),
|
|
325
|
-
commandMenuSeparator('tab-danger-separator'),
|
|
326
|
-
commandMenuEntry<WorkbenchEditorCommandContext>(WORKBENCH_EDITOR_DELETE_COMMAND_ID, {
|
|
327
|
-
surfaces: [WORKBENCH_COMMAND_SURFACE_EDITOR],
|
|
328
|
-
}),
|
|
329
385
|
];
|
|
330
386
|
}
|
|
331
387
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { MouseEvent } from 'react';
|
|
2
|
+
|
|
3
|
+
const NATIVE_CONTEXT_MENU_SELECTOR =
|
|
4
|
+
'input, textarea, select, [contenteditable="true"], .monaco-editor, .workspace-editor__monaco, .cm-editor';
|
|
5
|
+
|
|
6
|
+
export function shouldAllowNativeBrowserContextMenu(target: EventTarget | null): boolean {
|
|
7
|
+
if (!(target instanceof Element)) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return Boolean(target.closest(NATIVE_CONTEXT_MENU_SELECTOR));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function suppressNativeBrowserContextMenu(event: MouseEvent<HTMLElement>) {
|
|
15
|
+
if (!shouldAllowNativeBrowserContextMenu(event.target)) {
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EditorTabs, type EditorTabsProps } from '../../primitives/workbench-editor';
|
|
2
|
+
import { useWorkbenchEditorTabContextMenu } from './useWorkbenchEditorTabContextMenu';
|
|
3
|
+
|
|
4
|
+
export interface WorkbenchEditorTabsProps extends EditorTabsProps {
|
|
5
|
+
/**
|
|
6
|
+
* Optional bulk close. Defaults to calling `onClose` for every closable tab.
|
|
7
|
+
*/
|
|
8
|
+
readonly onCloseAll?: (() => void) | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Optional close-others. Defaults to calling `onClose` for every other closable tab.
|
|
11
|
+
*/
|
|
12
|
+
readonly onCloseOthers?: ((tabId: string) => void) | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Editor tab strip with a built-in Close / Close others / Close all context menu.
|
|
17
|
+
* Intended for `WorkbenchStandaloneShell` secondary areas that own tab state in the host.
|
|
18
|
+
* Tabs with `closable: false` keep Close disabled and are skipped by Close others / Close all.
|
|
19
|
+
*/
|
|
20
|
+
export function WorkbenchEditorTabs({
|
|
21
|
+
onClose,
|
|
22
|
+
onCloseAll,
|
|
23
|
+
onCloseOthers,
|
|
24
|
+
onSelect,
|
|
25
|
+
onTabContextMenu,
|
|
26
|
+
tabs,
|
|
27
|
+
...props
|
|
28
|
+
}: WorkbenchEditorTabsProps) {
|
|
29
|
+
const tabContextMenu = useWorkbenchEditorTabContextMenu({
|
|
30
|
+
onClose: onClose ?? (() => undefined),
|
|
31
|
+
onCloseAll,
|
|
32
|
+
onCloseOthers,
|
|
33
|
+
onSelectTab: onSelect,
|
|
34
|
+
tabs,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
<EditorTabs
|
|
40
|
+
{...props}
|
|
41
|
+
onClose={onClose}
|
|
42
|
+
onSelect={onSelect}
|
|
43
|
+
onTabContextMenu={(tabId, event) => {
|
|
44
|
+
tabContextMenu.onTabContextMenu(tabId, event);
|
|
45
|
+
onTabContextMenu?.(tabId, event);
|
|
46
|
+
}}
|
|
47
|
+
tabs={tabs}
|
|
48
|
+
/>
|
|
49
|
+
{tabContextMenu.contextMenu}
|
|
50
|
+
</>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import type { EditorTabDropPosition } from '../../primitives/workbench-editor';
|
|
2
|
+
|
|
3
|
+
export const EDITOR_TAB_DRAG_DATA_TYPE = 'application/x-workbench-kit-editor-tab' as const;
|
|
4
|
+
|
|
5
|
+
export interface EditorTabDragPayload {
|
|
6
|
+
readonly groupId: string;
|
|
7
|
+
readonly tabId: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface EditorTabDropTarget {
|
|
11
|
+
readonly position: EditorTabDropPosition;
|
|
12
|
+
readonly tabId: string;
|
|
13
|
+
readonly targetIndex: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface EditorDropTargetElement {
|
|
17
|
+
getBoundingClientRect(): Pick<DOMRect, 'left' | 'width'>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface EditorTabLike {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function readEditorTabDragPayload(
|
|
25
|
+
dataTransfer: Pick<DataTransfer, 'getData'>,
|
|
26
|
+
): EditorTabDragPayload | null {
|
|
27
|
+
try {
|
|
28
|
+
const rawPayload = dataTransfer.getData(EDITOR_TAB_DRAG_DATA_TYPE);
|
|
29
|
+
if (!rawPayload) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const payload = JSON.parse(rawPayload) as Partial<EditorTabDragPayload>;
|
|
34
|
+
if (typeof payload.groupId !== 'string' || typeof payload.tabId !== 'string') {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
groupId: payload.groupId,
|
|
40
|
+
tabId: payload.tabId,
|
|
41
|
+
};
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function isEditorTabsScrollerEventTarget(target: EventTarget | null): boolean {
|
|
48
|
+
if (!(target instanceof Element)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (target.closest('.ui-editor-tabs__tab')) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return Boolean(target.closest('.ui-editor-tabs__scroller'));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function resolveEditorTabDropTarget<TTab extends EditorTabLike>({
|
|
60
|
+
clientX,
|
|
61
|
+
draggedTab,
|
|
62
|
+
groupId,
|
|
63
|
+
preferredPosition,
|
|
64
|
+
tabs,
|
|
65
|
+
target,
|
|
66
|
+
targetTabId,
|
|
67
|
+
}: {
|
|
68
|
+
readonly clientX: number;
|
|
69
|
+
readonly draggedTab: EditorTabDragPayload;
|
|
70
|
+
readonly groupId: string;
|
|
71
|
+
readonly preferredPosition?: EditorTabDropPosition | undefined;
|
|
72
|
+
readonly tabs: readonly TTab[];
|
|
73
|
+
readonly target: EditorDropTargetElement;
|
|
74
|
+
readonly targetTabId: string;
|
|
75
|
+
}): EditorTabDropTarget | null {
|
|
76
|
+
const targetTabIndex = tabs.findIndex((tab) => tab.id === targetTabId);
|
|
77
|
+
if (targetTabIndex < 0) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const position = preferredPosition ?? getEditorTabDropPosition(target, clientX);
|
|
82
|
+
const targetIndex = position === 'after' ? targetTabIndex + 1 : targetTabIndex;
|
|
83
|
+
if (isEditorTabMoveNoop({ draggedTab, groupId, tabs, targetIndex })) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
position,
|
|
89
|
+
tabId: targetTabId,
|
|
90
|
+
targetIndex,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function resolveEditorTabStripDropTarget<TTab extends EditorTabLike>({
|
|
95
|
+
draggedTab,
|
|
96
|
+
groupId,
|
|
97
|
+
tabs,
|
|
98
|
+
}: {
|
|
99
|
+
readonly draggedTab: EditorTabDragPayload;
|
|
100
|
+
readonly groupId: string;
|
|
101
|
+
readonly tabs: readonly TTab[];
|
|
102
|
+
}): EditorTabDropTarget | null {
|
|
103
|
+
const lastTab = tabs[tabs.length - 1];
|
|
104
|
+
if (!lastTab) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const targetIndex = tabs.length;
|
|
109
|
+
if (isEditorTabMoveNoop({ draggedTab, groupId, tabs, targetIndex })) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
position: 'after',
|
|
115
|
+
tabId: lastTab.id,
|
|
116
|
+
targetIndex,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function isEditorTabMoveNoop<TTab extends EditorTabLike>({
|
|
121
|
+
draggedTab,
|
|
122
|
+
groupId,
|
|
123
|
+
tabs,
|
|
124
|
+
targetIndex,
|
|
125
|
+
}: {
|
|
126
|
+
readonly draggedTab: EditorTabDragPayload;
|
|
127
|
+
readonly groupId: string;
|
|
128
|
+
readonly tabs: readonly TTab[];
|
|
129
|
+
readonly targetIndex: number;
|
|
130
|
+
}): boolean {
|
|
131
|
+
if (draggedTab.groupId !== groupId) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const sourceIndex = tabs.findIndex((tab) => tab.id === draggedTab.tabId);
|
|
136
|
+
return sourceIndex >= 0 && (targetIndex === sourceIndex || targetIndex === sourceIndex + 1);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function getEditorTabDropPosition(
|
|
140
|
+
target: EditorDropTargetElement,
|
|
141
|
+
clientX: number,
|
|
142
|
+
): EditorTabDropPosition {
|
|
143
|
+
const rect = target.getBoundingClientRect();
|
|
144
|
+
if (rect.width <= 0) {
|
|
145
|
+
return 'after';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return clientX < rect.left + rect.width / 2 ? 'before' : 'after';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function normalizeEditorTabReorderIndex({
|
|
152
|
+
index,
|
|
153
|
+
sourceIndex,
|
|
154
|
+
tabCount,
|
|
155
|
+
}: {
|
|
156
|
+
index: number;
|
|
157
|
+
sourceIndex: number;
|
|
158
|
+
tabCount: number;
|
|
159
|
+
}): number {
|
|
160
|
+
const clampedIndex = Math.max(0, Math.min(index, tabCount));
|
|
161
|
+
return clampedIndex > sourceIndex ? clampedIndex - 1 : clampedIndex;
|
|
162
|
+
}
|