@workbench-kit/react 0.0.2-prototype.0.2.5 → 0.0.2-prototype.0.2.8
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 +20 -18
- package/src/index.ts +27 -27
- package/src/jdw/JsonCodeEditorPane.tsx +7 -6
- package/src/json-config/JsonConfigWorkbench.tsx +1 -1
- package/src/layout/sidebar/SidebarActionIconBar.tsx +3 -3
- package/src/layout/sidebar/WorkbenchSidebarActions.tsx +1 -1
- package/src/modal/Modal.tsx +55 -25
- package/src/modal/ModalTitlebar.tsx +8 -8
- package/src/modal/useModalFocusTrap.ts +142 -0
- package/src/modal/useModalWindowFrame.ts +2 -2
- package/src/primitives/absolute-box/AbsoluteBox.tsx +4 -4
- package/src/primitives/button/Button.tsx +4 -4
- package/src/primitives/catalog-browse-card/CatalogBrowseCard.tsx +6 -6
- package/src/primitives/catalog-browse-pane/CatalogBrowsePane.tsx +15 -15
- package/src/primitives/catalog-filter-overlay/CatalogFilterOverlay.tsx +2 -2
- package/src/primitives/checkbox/Checkbox.tsx +1 -1
- package/src/primitives/chip/Chip.tsx +2 -2
- package/src/primitives/codicon/Codicon.tsx +1 -1
- package/src/primitives/file-icon/FileIcon.tsx +1 -1
- package/src/primitives/icon-button/IconButton.tsx +1 -1
- package/src/primitives/library-detail-layout/LibraryDetailLayout.tsx +5 -5
- package/src/primitives/library-facet-filter-panel/LibraryFacetFilterPanel.tsx +12 -12
- package/src/primitives/library-facet-filter-strip/LibraryFacetFilterStrip.tsx +4 -4
- package/src/primitives/number-input/NumberInput.tsx +5 -5
- package/src/primitives/record-media-hero/RecordMediaHero.tsx +6 -6
- package/src/primitives/scroll-area/ScrollArea.tsx +5 -5
- package/src/primitives/scroll-area-infinite-load/useScrollAreaInfiniteLoad.ts +5 -5
- package/src/primitives/searchable-multi-select/SearchableMultiSelect.tsx +7 -7
- package/src/primitives/text-area/TextArea.tsx +1 -1
- package/src/primitives/text-input/TextInput.tsx +1 -1
- package/src/primitives/workbench-media-slot/WorkbenchMediaPlaceholder.tsx +2 -2
- package/src/primitives/workbench-media-slot/WorkbenchMediaSlot.tsx +9 -9
- package/src/primitives/workbench-thumbnail/WorkbenchThumbnail.tsx +4 -4
- package/src/styles.css +1 -2
- package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +2 -2
- package/src/workbench/chat/ChatCommandProposalCard.tsx +4 -4
- package/src/workbench/chat/ChatConversationBar.tsx +3 -3
- package/src/workbench/chat/ChatHistoryMenu.tsx +1 -1
- package/src/workbench/chat/ChatMessageCollapsible.tsx +4 -0
- package/src/workbench/chat/ChatMessageItem.tsx +68 -10
- package/src/workbench/chat/ChatMessageList.tsx +1 -1
- package/src/workbench/chat/ChatPanel.tsx +32 -23
- package/src/workbench/chat/ChatPhasedRunProgress.tsx +86 -13
- package/src/workbench/chat/ChatRenameDialog.tsx +1 -1
- package/src/workbench/chat/chat-conversation.css +2 -2
- package/src/workbench/chat/chat-ui.css +8 -0
- package/src/workbench/chat/chatConversation.ts +2 -2
- package/src/workbench/chat/chatMessageMeta.tsx +4 -4
- package/src/workbench/chat/index.ts +1 -0
- package/src/workbench/chat/types.ts +7 -7
- package/src/workbench/chat/useCancelRuntimeOnUnmount.ts +4 -4
- package/src/workbench/chat/useChatPrependPagination.ts +10 -10
- package/src/workbench/chat/useSlashCommandSuggest.ts +1 -1
- package/src/workbench/{WorkbenchModalPortal.tsx → chrome/WorkbenchModalPortal.tsx} +1 -1
- package/src/workbench/chrome/workbench-chrome.css +4 -0
- package/src/workbench/{CommandGroupShell.tsx → commands/CommandGroupShell.tsx} +2 -2
- package/src/workbench/{CommandList.tsx → commands/CommandList.tsx} +5 -5
- package/src/workbench/{CommandPalette.tsx → commands/CommandPalette.tsx} +16 -42
- package/src/workbench/{ConfirmationFlow.tsx → commands/ConfirmationFlow.tsx} +5 -5
- package/src/workbench/{command-model.ts → commands/command-model.ts} +5 -1
- package/src/workbench/{commands.ts → commands/commands.ts} +1 -1
- package/src/workbench/{WorkbenchEditorTabs.tsx → editor/WorkbenchEditorTabs.tsx} +1 -1
- package/src/workbench/{editor-tabs-dnd.ts → editor/editor-tabs-dnd.ts} +1 -1
- package/src/workbench/{editorTabContextMenu.ts → editor/editorTabContextMenu.ts} +2 -2
- package/src/workbench/{useEditorTabsStripDnd.ts → editor/useEditorTabsStripDnd.ts} +1 -1
- package/src/workbench/{useWorkbenchEditorTabContextMenu.tsx → editor/useWorkbenchEditorTabContextMenu.tsx} +1 -1
- package/src/workbench/editor-tabs/index.ts +9 -9
- package/src/workbench/index.ts +93 -74
- package/src/workbench/management/ExtensionManagementPanel.tsx +31 -2
- package/src/workbench/management/ExtensionManagementSidebar.tsx +18 -1
- package/src/workbench/management/IntegrationsShell.tsx +1 -1
- package/src/workbench/management/WorkbenchDialogFrame.tsx +2 -2
- package/src/workbench/management/extension-install-approval.ts +72 -0
- package/src/workbench/management/index.ts +7 -0
- package/src/workbench/management/types.ts +14 -1
- package/src/workbench/{MarkdownPreview.tsx → markdown/MarkdownPreview.tsx} +22 -7
- package/src/workbench/markdown/markdownRemarkPlugins.ts +12 -0
- package/src/workbench/markdown/sanitizeMarkdownHref.ts +29 -0
- package/src/workbench/{ActivityBar.tsx → shell/ActivityBar.tsx} +8 -8
- package/src/workbench/{ArtifactShell.tsx → shell/ArtifactShell.tsx} +25 -25
- package/src/workbench/{SplitView.tsx → shell/SplitView.tsx} +3 -3
- package/src/workbench/{StatusBar.tsx → shell/StatusBar.tsx} +8 -8
- package/src/workbench/{StructuredArtifactEditor.tsx → shell/StructuredArtifactEditor.tsx} +9 -9
- package/src/workbench/{Timeline.tsx → shell/Timeline.tsx} +18 -18
- package/src/workbench/{WorkbenchCanvasShell.defaults.ts → shell/WorkbenchCanvasShell.defaults.ts} +1 -1
- package/src/workbench/{WorkbenchCanvasShell.model.ts → shell/WorkbenchCanvasShell.model.ts} +5 -5
- package/src/workbench/{WorkbenchCanvasShell.tsx → shell/WorkbenchCanvasShell.tsx} +6 -6
- package/src/workbench/{WorkbenchDesktopTitleBar.tsx → shell/WorkbenchDesktopTitleBar.tsx} +15 -15
- package/src/workbench/{WorkbenchShell.tsx → shell/WorkbenchShell.tsx} +5 -5
- package/src/workbench/{WorkbenchShellTitleBarLayoutControls.tsx → shell/WorkbenchShellTitleBarLayoutControls.tsx} +12 -12
- package/src/workbench/{WorkbenchStandaloneShell.tsx → shell/WorkbenchStandaloneShell.tsx} +4 -4
- package/src/workbench/{WorkbenchViewEditor.tsx → shell/WorkbenchViewEditor.tsx} +7 -7
- package/src/workbench/{WorkbenchViewSidebar.tsx → shell/WorkbenchViewSidebar.tsx} +7 -7
- package/src/workbench/{WorkbenchWindowChromeControls.tsx → shell/WorkbenchWindowChromeControls.tsx} +18 -15
- package/src/workbench/{shell.ts → shell/shell.ts} +18 -12
- package/src/workbench/{shellViewModel.ts → shell/shellViewModel.ts} +3 -3
- package/src/workbench/{standalone.ts → shell/standalone.ts} +2 -2
- package/src/workbench/{useDeferredWorkbenchMount.ts → shell/useDeferredWorkbenchMount.ts} +3 -3
- package/src/workbench/{useWorkbenchAppearanceDocumentSync.tsx → shell/useWorkbenchAppearanceDocumentSync.tsx} +1 -1
- package/src/workbench/{useWorkbenchSidebarActionBarDnd.ts → shell/useWorkbenchSidebarActionBarDnd.ts} +1 -1
- package/src/workbench/{useWorkbenchSidebarViewPlacementDropZone.ts → shell/useWorkbenchSidebarViewPlacementDropZone.ts} +2 -2
- package/src/workbench/{workbenchViewRouteState.ts → shell/workbenchViewRouteState.ts} +4 -4
- package/src/workbench/{WorkbenchThemeProvider.tsx → theme/WorkbenchThemeProvider.tsx} +4 -4
- package/src/workbench/{theme.ts → theme/theme.ts} +1 -1
- package/src/workbench/{themePresets.ts → theme/themePresets.ts} +2 -2
- package/src/workbench/workspace/WorkspaceEditorPanel.tsx +1 -1
- package/src/workbench/workspace/workspaceJsonDiagnostics.ts +6 -5
- package/src/workbench/jdw/jdw-editors.css +0 -4
- package/src/workbench/jdw/jdw.css +0 -2
- package/src/workbench/markdownRemarkPlugins.ts +0 -4
- package/src/workbench/workbench-chrome.css +0 -4
- /package/src/workbench/{WorkbenchPlatformContext.tsx → chrome/WorkbenchPlatformContext.tsx} +0 -0
- /package/src/workbench/{workbenchModalViewState.ts → chrome/workbenchModalViewState.ts} +0 -0
- /package/src/workbench/{workbenchOverlaysContext.tsx → chrome/workbenchOverlaysContext.tsx} +0 -0
- /package/src/workbench/{workbenchPlatformChrome.ts → chrome/workbenchPlatformChrome.ts} +0 -0
- /package/src/workbench/{ShortcutCommandBridge.tsx → commands/ShortcutCommandBridge.tsx} +0 -0
- /package/src/workbench/{command-execution-policy.ts → commands/command-execution-policy.ts} +0 -0
- /package/src/workbench/{keyboard.ts → commands/keyboard.ts} +0 -0
- /package/src/workbench/{workbenchContextMenu.ts → commands/workbenchContextMenu.ts} +0 -0
- /package/src/workbench/{activityBarOrder.ts → shell/activityBarOrder.ts} +0 -0
- /package/src/workbench/{appearanceLabels.ts → shell/appearanceLabels.ts} +0 -0
- /package/src/workbench/{hardReset.ts → shell/hardReset.ts} +0 -0
- /package/src/workbench/{shellPresets.ts → shell/shellPresets.ts} +0 -0
- /package/src/workbench/{shellState.ts → shell/shellState.ts} +0 -0
- /package/src/workbench/{sidebarViewPlacementDnd.ts → shell/sidebarViewPlacementDnd.ts} +0 -0
- /package/src/workbench/{status.ts → shell/status.ts} +0 -0
- /package/src/workbench/{useWorkbenchSidebarLayout.tsx → shell/useWorkbenchSidebarLayout.tsx} +0 -0
- /package/src/workbench/{useWorkbenchStandaloneShellStateSync.tsx → shell/useWorkbenchStandaloneShellStateSync.tsx} +0 -0
- /package/src/workbench/{workbenchSidebarLayoutContext.ts → shell/workbenchSidebarLayoutContext.ts} +0 -0
- /package/src/workbench/{workbenchStandaloneShellReactContext.tsx → shell/workbenchStandaloneShellReactContext.tsx} +0 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { useEffect, type RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
const FOCUSABLE_SELECTOR = [
|
|
4
|
+
'a[href]',
|
|
5
|
+
'button:not([disabled])',
|
|
6
|
+
'textarea:not([disabled])',
|
|
7
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
8
|
+
'select:not([disabled])',
|
|
9
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
10
|
+
].join(',');
|
|
11
|
+
|
|
12
|
+
function isFocusable(element: HTMLElement): boolean {
|
|
13
|
+
if (element.hasAttribute('disabled') || element.getAttribute('aria-disabled') === 'true') {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (element.getAttribute('aria-hidden') === 'true') {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
// Explicit tabindex="-1" removes the node from the tab order.
|
|
20
|
+
// Do not use element.tabIndex >= 0: jsdom reports -1 for native buttons.
|
|
21
|
+
if (element.getAttribute('tabindex') === '-1') {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const style = window.getComputedStyle(element);
|
|
25
|
+
return style.display !== 'none' && style.visibility !== 'hidden';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function listFocusable(container: HTMLElement): HTMLElement[] {
|
|
29
|
+
return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(
|
|
30
|
+
isFocusable,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UseModalFocusTrapOptions {
|
|
35
|
+
readonly closeOnEscape?: boolean;
|
|
36
|
+
readonly containerRef: RefObject<HTMLElement | null>;
|
|
37
|
+
/** When false, skip trap/restore (for dialogs that stay mounted while closed). Default true. */
|
|
38
|
+
readonly enabled?: boolean;
|
|
39
|
+
readonly initialFocusRef?: RefObject<HTMLElement | null>;
|
|
40
|
+
readonly onClose: () => void;
|
|
41
|
+
readonly restoreFocusOnClose?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Trap Tab focus inside a mounted modal dialog and restore focus on unmount.
|
|
46
|
+
* Escape dismisses when `closeOnEscape` is true (default).
|
|
47
|
+
*/
|
|
48
|
+
export function useModalFocusTrap({
|
|
49
|
+
closeOnEscape = true,
|
|
50
|
+
containerRef,
|
|
51
|
+
enabled = true,
|
|
52
|
+
initialFocusRef,
|
|
53
|
+
onClose,
|
|
54
|
+
restoreFocusOnClose = true,
|
|
55
|
+
}: UseModalFocusTrapOptions): void {
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (!enabled) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const previousFocus =
|
|
62
|
+
document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
63
|
+
|
|
64
|
+
const focusInitial = () => {
|
|
65
|
+
const container = containerRef.current;
|
|
66
|
+
if (!container) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const preferred = initialFocusRef?.current;
|
|
71
|
+
if (preferred && container.contains(preferred)) {
|
|
72
|
+
preferred.focus();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const focusables = listFocusable(container);
|
|
77
|
+
if (focusables[0]) {
|
|
78
|
+
focusables[0].focus();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!container.hasAttribute('tabindex')) {
|
|
83
|
+
container.tabIndex = -1;
|
|
84
|
+
}
|
|
85
|
+
container.focus();
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const frame = window.requestAnimationFrame(focusInitial);
|
|
89
|
+
|
|
90
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
91
|
+
if (event.key === 'Escape' && closeOnEscape) {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
event.stopPropagation();
|
|
94
|
+
onClose();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (event.key !== 'Tab') {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const container = containerRef.current;
|
|
103
|
+
if (!container) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const focusables = listFocusable(container);
|
|
108
|
+
if (focusables.length === 0) {
|
|
109
|
+
event.preventDefault();
|
|
110
|
+
container.focus();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const first = focusables[0]!;
|
|
115
|
+
const last = focusables[focusables.length - 1]!;
|
|
116
|
+
const active = document.activeElement;
|
|
117
|
+
|
|
118
|
+
if (event.shiftKey) {
|
|
119
|
+
if (active === first || !container.contains(active)) {
|
|
120
|
+
event.preventDefault();
|
|
121
|
+
last.focus();
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (active === last || !container.contains(active)) {
|
|
127
|
+
event.preventDefault();
|
|
128
|
+
first.focus();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
window.addEventListener('keydown', handleKeyDown, true);
|
|
133
|
+
|
|
134
|
+
return () => {
|
|
135
|
+
window.cancelAnimationFrame(frame);
|
|
136
|
+
window.removeEventListener('keydown', handleKeyDown, true);
|
|
137
|
+
if (restoreFocusOnClose && previousFocus?.isConnected) {
|
|
138
|
+
previousFocus.focus();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}, [closeOnEscape, containerRef, enabled, initialFocusRef, onClose, restoreFocusOnClose]);
|
|
142
|
+
}
|
|
@@ -9,8 +9,8 @@ import { useModalResize } from './useModalResize';
|
|
|
9
9
|
|
|
10
10
|
export interface UseModalWindowFrameOptions {
|
|
11
11
|
defaultMaximized: boolean;
|
|
12
|
-
defaultHeight?: number
|
|
13
|
-
defaultWidth?: number
|
|
12
|
+
defaultHeight?: number;
|
|
13
|
+
defaultWidth?: number;
|
|
14
14
|
minHeight: number;
|
|
15
15
|
minWidth: number;
|
|
16
16
|
}
|
|
@@ -9,12 +9,12 @@ export interface WorkbenchRect {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface AbsoluteBoxProps {
|
|
12
|
-
background?: string
|
|
12
|
+
background?: string;
|
|
13
13
|
children?: ReactNode;
|
|
14
|
-
className?: string
|
|
15
|
-
overflow?: CSSProperties['overflow']
|
|
14
|
+
className?: string;
|
|
15
|
+
overflow?: CSSProperties['overflow'];
|
|
16
16
|
rect: WorkbenchRect;
|
|
17
|
-
style?: CSSProperties
|
|
17
|
+
style?: CSSProperties;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function AbsoluteBox({
|
|
@@ -6,10 +6,10 @@ import { cx } from '../../utils/cx';
|
|
|
6
6
|
type ButtonVariant = 'default' | 'primary' | 'danger';
|
|
7
7
|
|
|
8
8
|
export interface ButtonProps extends ComponentPropsWithRef<'button'> {
|
|
9
|
-
block?: boolean
|
|
10
|
-
compact?: boolean
|
|
11
|
-
icon?: string
|
|
12
|
-
secondary?: boolean
|
|
9
|
+
block?: boolean;
|
|
10
|
+
compact?: boolean;
|
|
11
|
+
icon?: string;
|
|
12
|
+
secondary?: boolean;
|
|
13
13
|
variant?: ButtonVariant;
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -11,9 +11,9 @@ export interface CatalogBrowseCardProps extends Omit<
|
|
|
11
11
|
'children' | 'title'
|
|
12
12
|
> {
|
|
13
13
|
description?: ReactNode;
|
|
14
|
-
icon?: string
|
|
15
|
-
imageAlt?: string
|
|
16
|
-
imageUrl?: string | null
|
|
14
|
+
icon?: string;
|
|
15
|
+
imageAlt?: string;
|
|
16
|
+
imageUrl?: string | null;
|
|
17
17
|
label: ReactNode;
|
|
18
18
|
/**
|
|
19
19
|
* Custom media content for the icon/cover region. When set, replaces the
|
|
@@ -23,15 +23,15 @@ export interface CatalogBrowseCardProps extends Omit<
|
|
|
23
23
|
/** Overlay content inside the media region (badges, status chips, etc.). */
|
|
24
24
|
mediaOverlay?: ReactNode;
|
|
25
25
|
meta?: ReactNode;
|
|
26
|
-
selected?: boolean
|
|
26
|
+
selected?: boolean;
|
|
27
27
|
/**
|
|
28
28
|
* Secondary actions outside the primary hit target (for example Assign).
|
|
29
29
|
* When set, the root becomes a non-button container and click/drag handlers
|
|
30
30
|
* apply to the main control only.
|
|
31
31
|
*/
|
|
32
32
|
trailing?: ReactNode;
|
|
33
|
-
tooltip?: string
|
|
34
|
-
variant?: CatalogBrowseCardVariant
|
|
33
|
+
tooltip?: string;
|
|
34
|
+
variant?: CatalogBrowseCardVariant;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export function CatalogBrowseCard({
|
|
@@ -33,12 +33,12 @@ export type CatalogBrowseViewMode = 'grid' | 'list';
|
|
|
33
33
|
* Hosts with richer cards should pass `renderGridItem` / `renderListItem`.
|
|
34
34
|
*/
|
|
35
35
|
export interface CatalogBrowseItem {
|
|
36
|
-
readonly description?: string | null
|
|
36
|
+
readonly description?: string | null;
|
|
37
37
|
readonly id: string;
|
|
38
|
-
readonly imageAlt?: string
|
|
39
|
-
readonly imageUrl?: string | null
|
|
38
|
+
readonly imageAlt?: string;
|
|
39
|
+
readonly imageUrl?: string | null;
|
|
40
40
|
readonly label: string;
|
|
41
|
-
readonly meta?: string | null
|
|
41
|
+
readonly meta?: string | null;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export interface CatalogBrowseItemRenderState {
|
|
@@ -48,17 +48,17 @@ export interface CatalogBrowseItemRenderState {
|
|
|
48
48
|
export interface CatalogBrowsePaneProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
|
|
49
49
|
readonly clearSearchLabel: string;
|
|
50
50
|
readonly emptyMessage: string;
|
|
51
|
-
readonly errorMessage?: string | null
|
|
51
|
+
readonly errorMessage?: string | null;
|
|
52
52
|
/** Slot between search and sort/view controls (facet trigger, chips, etc.). */
|
|
53
53
|
readonly facetStrip?: ReactNode;
|
|
54
|
-
readonly gridAriaLabel?: string
|
|
54
|
+
readonly gridAriaLabel?: string;
|
|
55
55
|
/** Visual label for the grid view-mode segment (string or icon node). */
|
|
56
56
|
readonly gridLabel?: ReactNode;
|
|
57
57
|
readonly hasMore: boolean;
|
|
58
58
|
readonly isLoading: boolean;
|
|
59
59
|
readonly isLoadingMore: boolean;
|
|
60
60
|
readonly items: ReadonlyArray<CatalogBrowseItem>;
|
|
61
|
-
readonly listAriaLabel?: string
|
|
61
|
+
readonly listAriaLabel?: string;
|
|
62
62
|
/** Visual label for the list view-mode segment (string or icon node). */
|
|
63
63
|
readonly listLabel?: ReactNode;
|
|
64
64
|
readonly loadingMessage: string;
|
|
@@ -66,11 +66,11 @@ export interface CatalogBrowsePaneProps extends Omit<ComponentPropsWithRef<'div'
|
|
|
66
66
|
((itemId: string, itemLabel: string, event: ReactMouseEvent<HTMLElement>) => void) | undefined;
|
|
67
67
|
readonly onLoadMore: () => void;
|
|
68
68
|
readonly onOpenItem: (itemId: string) => void;
|
|
69
|
-
readonly onRefresh?: (() => void) | null
|
|
69
|
+
readonly onRefresh?: (() => void) | null;
|
|
70
70
|
readonly onSearchQueryChange: (query: string) => void;
|
|
71
|
-
readonly onSortChange?: (
|
|
71
|
+
readonly onSortChange?: (sort: string) => void;
|
|
72
72
|
readonly onViewModeChange: (viewMode: CatalogBrowseViewMode) => void;
|
|
73
|
-
readonly refreshLabel?: string | null
|
|
73
|
+
readonly refreshLabel?: string | null;
|
|
74
74
|
readonly renderGridItem?:
|
|
75
75
|
((item: CatalogBrowseItem, state: CatalogBrowseItemRenderState) => ReactNode) | undefined;
|
|
76
76
|
readonly renderListItem?:
|
|
@@ -78,14 +78,14 @@ export interface CatalogBrowsePaneProps extends Omit<ComponentPropsWithRef<'div'
|
|
|
78
78
|
readonly searchAriaLabel: string;
|
|
79
79
|
readonly searchPlaceholder: string;
|
|
80
80
|
readonly searchQuery: string;
|
|
81
|
-
readonly selectedItemId?: string | null
|
|
82
|
-
readonly sort?: string
|
|
83
|
-
readonly sortAriaLabel?: string
|
|
84
|
-
readonly sortOptions?: ReadonlyArray<{ label: string; value: string }
|
|
81
|
+
readonly selectedItemId?: string | null;
|
|
82
|
+
readonly sort?: string;
|
|
83
|
+
readonly sortAriaLabel?: string;
|
|
84
|
+
readonly sortOptions?: ReadonlyArray<{ label: string; value: string }>;
|
|
85
85
|
/** Extra trailing controls after built-in sort / view mode (before refresh). */
|
|
86
86
|
readonly toolbarTrailing?: ReactNode;
|
|
87
87
|
readonly viewMode: CatalogBrowseViewMode;
|
|
88
|
-
readonly viewModeAriaLabel?: string
|
|
88
|
+
readonly viewModeAriaLabel?: string;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
export function CatalogBrowsePane({
|
|
@@ -13,10 +13,10 @@ export interface CatalogFilterOverlayProps extends Omit<
|
|
|
13
13
|
* When true, Clear stays mounted and sized but is not actionable.
|
|
14
14
|
* Keeps the title row height stable across selection changes.
|
|
15
15
|
*/
|
|
16
|
-
readonly clearDisabled?: boolean
|
|
16
|
+
readonly clearDisabled?: boolean;
|
|
17
17
|
readonly clearLabel: string;
|
|
18
18
|
readonly onClear: () => void;
|
|
19
|
-
readonly ref?: Ref<HTMLDivElement
|
|
19
|
+
readonly ref?: Ref<HTMLDivElement>;
|
|
20
20
|
readonly title: ReactNode;
|
|
21
21
|
readonly titleId: string;
|
|
22
22
|
}
|
|
@@ -3,7 +3,7 @@ import type { ChangeEvent, ComponentPropsWithRef, ReactNode } from 'react';
|
|
|
3
3
|
import { cx } from '../../utils/cx';
|
|
4
4
|
|
|
5
5
|
export interface CheckboxProps extends Omit<ComponentPropsWithRef<'input'>, 'type'> {
|
|
6
|
-
label?: ReactNode
|
|
6
|
+
label?: ReactNode;
|
|
7
7
|
onCheckedChange?: (checked: boolean, event: ChangeEvent<HTMLInputElement>) => void;
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -4,9 +4,9 @@ import { Button } from '../button';
|
|
|
4
4
|
import { cx } from '../../utils/cx';
|
|
5
5
|
|
|
6
6
|
export interface ChipProps extends Omit<ComponentPropsWithRef<'button'>, 'children'> {
|
|
7
|
-
count?: number
|
|
7
|
+
count?: number;
|
|
8
8
|
label: ReactNode;
|
|
9
|
-
onDismiss?: (
|
|
9
|
+
onDismiss?: () => void;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -4,7 +4,7 @@ import { cxCodicon } from '../../utils/codicon';
|
|
|
4
4
|
export interface CodiconProps extends Omit<ComponentPropsWithRef<'i'>, 'children'> {
|
|
5
5
|
icon: string;
|
|
6
6
|
/** When set, exposes the icon to assistive tech instead of aria-hidden. */
|
|
7
|
-
label?: string
|
|
7
|
+
label?: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/** VS Code codicon glyph (`codicon` font). Requires `@vscode/codicons` CSS in the app entry. Prefer `WorkbenchIcon` for new code. */
|
|
@@ -6,7 +6,7 @@ export const UI_FILE_ICON_CLASS = 'ui-file-icon';
|
|
|
6
6
|
|
|
7
7
|
export interface FileIconProps extends Omit<ComponentPropsWithRef<'i'>, 'children'> {
|
|
8
8
|
icon: string;
|
|
9
|
-
kind?: FileIconKind
|
|
9
|
+
kind?: FileIconKind;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function FileIcon({ className, icon, kind, ...props }: FileIconProps) {
|
|
@@ -7,7 +7,7 @@ import { cx } from '../../utils/cx';
|
|
|
7
7
|
type IconButtonVariant = 'default' | 'danger';
|
|
8
8
|
|
|
9
9
|
export interface IconButtonProps extends Omit<ComponentPropsWithRef<'button'>, 'children'> {
|
|
10
|
-
compact?: boolean
|
|
10
|
+
compact?: boolean;
|
|
11
11
|
icon: WorkbenchIconInput;
|
|
12
12
|
label: string;
|
|
13
13
|
variant?: IconButtonVariant;
|
|
@@ -13,13 +13,13 @@ export interface LibraryDetailLayoutProps extends Omit<
|
|
|
13
13
|
'children' | 'title'
|
|
14
14
|
> {
|
|
15
15
|
readonly actions?: ReactNode;
|
|
16
|
-
readonly backgroundImageUrl?: string | null
|
|
16
|
+
readonly backgroundImageUrl?: string | null;
|
|
17
17
|
readonly children?: ReactNode;
|
|
18
|
-
readonly coverAlt?: string
|
|
19
|
-
readonly coverImageUrl?: string | null
|
|
18
|
+
readonly coverAlt?: string;
|
|
19
|
+
readonly coverImageUrl?: string | null;
|
|
20
20
|
readonly description?: ReactNode;
|
|
21
|
-
readonly logoImageUrl?: string | null
|
|
22
|
-
readonly mode?: LibraryDetailLayoutMode
|
|
21
|
+
readonly logoImageUrl?: string | null;
|
|
22
|
+
readonly mode?: LibraryDetailLayoutMode;
|
|
23
23
|
readonly summary?: ReactNode;
|
|
24
24
|
readonly title: ReactNode;
|
|
25
25
|
readonly toolbar?: ReactNode;
|
|
@@ -38,7 +38,7 @@ export interface LibraryFacetSection {
|
|
|
38
38
|
* Uncontrolled initial collapsed state when `collapsibleSections` is true.
|
|
39
39
|
* When omitted, sections start expanded.
|
|
40
40
|
*/
|
|
41
|
-
readonly defaultCollapsed?: boolean
|
|
41
|
+
readonly defaultCollapsed?: boolean;
|
|
42
42
|
readonly fields: ReadonlyArray<LibraryFacetField>;
|
|
43
43
|
readonly id: string;
|
|
44
44
|
}
|
|
@@ -46,33 +46,33 @@ export interface LibraryFacetSection {
|
|
|
46
46
|
export interface LibraryFacetFilterPanelLabels {
|
|
47
47
|
readonly clearAll: string;
|
|
48
48
|
readonly clearChipAria: (chipLabel: string) => string;
|
|
49
|
-
readonly empty?: string
|
|
49
|
+
readonly empty?: string;
|
|
50
50
|
/** Aria/placeholder for searchable facet input. Default: "Search options". */
|
|
51
|
-
readonly filterOptions?: string
|
|
51
|
+
readonly filterOptions?: string;
|
|
52
52
|
/** Shown when option filter matches nothing. Default: "No matching options". */
|
|
53
|
-
readonly noMatchingOptions?: string
|
|
53
|
+
readonly noMatchingOptions?: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export interface LibraryFacetFilterPanelProps {
|
|
57
|
-
readonly activeChips?: ReadonlyArray<LibraryFacetActiveChip
|
|
58
|
-
readonly className?: string
|
|
57
|
+
readonly activeChips?: ReadonlyArray<LibraryFacetActiveChip>;
|
|
58
|
+
readonly className?: string;
|
|
59
59
|
/**
|
|
60
60
|
* When true, section headers toggle collapse.
|
|
61
61
|
* Default false — keeps all sections expanded.
|
|
62
62
|
*/
|
|
63
|
-
readonly collapsibleSections?: boolean
|
|
64
|
-
readonly description?: string
|
|
63
|
+
readonly collapsibleSections?: boolean;
|
|
64
|
+
readonly description?: string;
|
|
65
65
|
readonly labels: LibraryFacetFilterPanelLabels;
|
|
66
66
|
/** Required when `showActiveChips` is true (chip strip Clear). Host may own Clear otherwise. */
|
|
67
|
-
readonly onClearAll?: (
|
|
68
|
-
readonly onRemoveChip?: (
|
|
67
|
+
readonly onClearAll?: () => void;
|
|
68
|
+
readonly onRemoveChip?: (chipId: string) => void;
|
|
69
69
|
readonly onToggleFacetValue: (
|
|
70
70
|
fieldId: string,
|
|
71
71
|
value: string,
|
|
72
72
|
kind: LibraryFacetFieldKind,
|
|
73
73
|
) => void;
|
|
74
74
|
readonly resolveFieldLabel: (fieldId: string) => string;
|
|
75
|
-
readonly resolveSectionLabel?: (
|
|
75
|
+
readonly resolveSectionLabel?: (sectionId: string) => string;
|
|
76
76
|
readonly sections: ReadonlyArray<LibraryFacetSection>;
|
|
77
77
|
readonly selectedValues: Readonly<Record<string, readonly string[]>>;
|
|
78
78
|
/**
|
|
@@ -80,7 +80,7 @@ export interface LibraryFacetFilterPanelProps {
|
|
|
80
80
|
* selection). Hosts should place Clear in their own header chrome.
|
|
81
81
|
* Default true for backward compatibility.
|
|
82
82
|
*/
|
|
83
|
-
readonly showActiveChips?: boolean
|
|
83
|
+
readonly showActiveChips?: boolean;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
function sectionHasSelection(
|
|
@@ -26,7 +26,7 @@ export type LibraryFacetFieldKind = 'single-select' | 'multi-select';
|
|
|
26
26
|
export type LibraryFacetFieldPresentation = 'checklist' | 'searchable-multi';
|
|
27
27
|
|
|
28
28
|
export interface LibraryFacetFieldOption {
|
|
29
|
-
readonly count?: number
|
|
29
|
+
readonly count?: number;
|
|
30
30
|
readonly label: string;
|
|
31
31
|
readonly value: string;
|
|
32
32
|
}
|
|
@@ -43,7 +43,7 @@ export interface LibraryFacetField {
|
|
|
43
43
|
* Panel presentation hint. When omitted, long multi-select lists use
|
|
44
44
|
* `searchable-multi` and short lists use `checklist`.
|
|
45
45
|
*/
|
|
46
|
-
readonly presentation?: LibraryFacetFieldPresentation
|
|
46
|
+
readonly presentation?: LibraryFacetFieldPresentation;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
export interface LibraryFacetActiveChip {
|
|
@@ -61,9 +61,9 @@ export interface LibraryFacetFilterStripProps {
|
|
|
61
61
|
* When set with `onOpenMoreFilters`, replaces cascade show-more/less with a
|
|
62
62
|
* menu item that opens the fuller facet panel/dialog.
|
|
63
63
|
*/
|
|
64
|
-
readonly moreFiltersLabel?: string
|
|
64
|
+
readonly moreFiltersLabel?: string;
|
|
65
65
|
readonly onClearAll: () => void;
|
|
66
|
-
readonly onOpenMoreFilters?: (
|
|
66
|
+
readonly onOpenMoreFilters?: () => void;
|
|
67
67
|
readonly onShowLess: () => void;
|
|
68
68
|
readonly onShowMore: () => void;
|
|
69
69
|
readonly onToggleFacetValue: (
|
|
@@ -17,16 +17,16 @@ export interface NumberInputProps extends Omit<
|
|
|
17
17
|
TextInputProps,
|
|
18
18
|
'defaultValue' | 'onValueChange' | 'type' | 'value'
|
|
19
19
|
> {
|
|
20
|
-
defaultValue?: number
|
|
20
|
+
defaultValue?: number;
|
|
21
21
|
/**
|
|
22
22
|
* When true, `undefined` renders as an empty field. Clearing the input calls
|
|
23
23
|
* `onEmptyValue` (preferred) instead of `onValueChange`.
|
|
24
24
|
*/
|
|
25
|
-
nullable?: boolean
|
|
25
|
+
nullable?: boolean;
|
|
26
26
|
/** Fired when a nullable field is cleared. */
|
|
27
|
-
onEmptyValue?: (
|
|
28
|
-
onValueChange?: (
|
|
29
|
-
value?: number
|
|
27
|
+
onEmptyValue?: () => void;
|
|
28
|
+
onValueChange?: (value: number, event: ChangeEvent<HTMLInputElement>) => void;
|
|
29
|
+
value?: number;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function resolveStep(step: TextInputProps['step']): number {
|
|
@@ -9,12 +9,12 @@ import { WorkbenchMediaSlot } from '../workbench-media-slot';
|
|
|
9
9
|
export type RecordMediaHeroLayout = 'banner' | 'compact' | 'background';
|
|
10
10
|
|
|
11
11
|
export interface RecordMediaHeroProps extends ComponentPropsWithRef<'div'> {
|
|
12
|
-
alt?: string
|
|
13
|
-
fallbackIcon?: string
|
|
14
|
-
imageUrl?: string | null
|
|
15
|
-
layout?: RecordMediaHeroLayout
|
|
16
|
-
logoUrl?: string | null
|
|
17
|
-
maxWidth?: number | string
|
|
12
|
+
alt?: string;
|
|
13
|
+
fallbackIcon?: string;
|
|
14
|
+
imageUrl?: string | null;
|
|
15
|
+
layout?: RecordMediaHeroLayout;
|
|
16
|
+
logoUrl?: string | null;
|
|
17
|
+
maxWidth?: number | string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function resolveMaxWidth(maxWidth: number | string | undefined): CSSProperties['maxWidth'] {
|
|
@@ -19,11 +19,11 @@ export type ScrollAreaOrientation = 'both' | 'horizontal' | 'vertical';
|
|
|
19
19
|
export type ScrollAreaScrollbarVisibility = 'auto' | 'hidden' | 'overlay';
|
|
20
20
|
|
|
21
21
|
export interface ScrollAreaProps extends Omit<ComponentPropsWithRef<'div'>, 'children'> {
|
|
22
|
-
as?: ElementType
|
|
23
|
-
children?: ReactNode
|
|
24
|
-
gutter?: ScrollAreaGutter
|
|
25
|
-
orientation?: ScrollAreaOrientation
|
|
26
|
-
scrollbars?: ScrollAreaScrollbarVisibility
|
|
22
|
+
as?: ElementType;
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
gutter?: ScrollAreaGutter;
|
|
25
|
+
orientation?: ScrollAreaOrientation;
|
|
26
|
+
scrollbars?: ScrollAreaScrollbarVisibility;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
type OverlayThumb = {
|
|
@@ -3,13 +3,13 @@ import { useEffect, useRef, type RefObject } from 'react';
|
|
|
3
3
|
const DEFAULT_ROOT_MARGIN = '0px 0px 120px 0px';
|
|
4
4
|
|
|
5
5
|
export interface UseScrollAreaInfiniteLoadOptions {
|
|
6
|
-
enabled?: boolean
|
|
6
|
+
enabled?: boolean;
|
|
7
7
|
hasMore: boolean;
|
|
8
|
-
isLoading?: boolean
|
|
9
|
-
isLoadingMore?: boolean
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
isLoadingMore?: boolean;
|
|
10
10
|
onLoadMore: () => void | Promise<void>;
|
|
11
|
-
rootMargin?: string
|
|
12
|
-
scrollAreaRef?: RefObject<HTMLElement | null
|
|
11
|
+
rootMargin?: string;
|
|
12
|
+
scrollAreaRef?: RefObject<HTMLElement | null>;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface UseScrollAreaInfiniteLoadResult {
|
|
@@ -25,24 +25,24 @@ import {
|
|
|
25
25
|
} from './overlay';
|
|
26
26
|
|
|
27
27
|
export interface SearchableMultiSelectOption {
|
|
28
|
-
readonly count?: number
|
|
29
|
-
readonly disabled?: boolean
|
|
28
|
+
readonly count?: number;
|
|
29
|
+
readonly disabled?: boolean;
|
|
30
30
|
readonly label: string;
|
|
31
31
|
readonly value: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export interface SearchableMultiSelectProps {
|
|
35
35
|
readonly 'aria-label'?: string | undefined;
|
|
36
|
-
readonly className?: string
|
|
37
|
-
readonly disabled?: boolean
|
|
36
|
+
readonly className?: string;
|
|
37
|
+
readonly disabled?: boolean;
|
|
38
38
|
/** Shown when the query matches no options. Default: "No matching options". */
|
|
39
|
-
readonly emptyMessage?: string
|
|
39
|
+
readonly emptyMessage?: string;
|
|
40
40
|
/** Aria label for dismissible selected chips. Default: "Remove {label}". */
|
|
41
|
-
readonly getRemoveChipAriaLabel?: (
|
|
41
|
+
readonly getRemoveChipAriaLabel?: (optionLabel: string) => string;
|
|
42
42
|
readonly onValueToggle: (value: string) => void;
|
|
43
43
|
readonly options: ReadonlyArray<SearchableMultiSelectOption>;
|
|
44
44
|
/** Search input placeholder. Default: "Search". */
|
|
45
|
-
readonly searchPlaceholder?: string
|
|
45
|
+
readonly searchPlaceholder?: string;
|
|
46
46
|
readonly selectedValues: readonly string[];
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -7,7 +7,7 @@ type ControlWidth = 'default' | 'wide' | 'full';
|
|
|
7
7
|
export interface TextAreaProps extends ComponentPropsWithRef<'textarea'> {
|
|
8
8
|
controlWidth?: ControlWidth;
|
|
9
9
|
monospace?: boolean;
|
|
10
|
-
resize?: CSSProperties['resize']
|
|
10
|
+
resize?: CSSProperties['resize'];
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function TextArea({
|
|
@@ -7,7 +7,7 @@ export type ControlWidth = 'default' | 'wide' | 'full';
|
|
|
7
7
|
export interface TextInputProps extends ComponentPropsWithRef<'input'> {
|
|
8
8
|
controlWidth?: ControlWidth;
|
|
9
9
|
monospace?: boolean;
|
|
10
|
-
onValueChange?: (
|
|
10
|
+
onValueChange?: (value: string, event: ChangeEvent<HTMLInputElement>) => void;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function TextInput({
|
|
@@ -4,8 +4,8 @@ import { cxCodicon } from '../../utils/codicon';
|
|
|
4
4
|
import { cx } from '../../utils/cx';
|
|
5
5
|
|
|
6
6
|
export interface WorkbenchMediaPlaceholderProps extends ComponentPropsWithRef<'span'> {
|
|
7
|
-
icon?: string
|
|
8
|
-
iconClassName?: string
|
|
7
|
+
icon?: string;
|
|
8
|
+
iconClassName?: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -6,20 +6,20 @@ import { useWorkbenchMediaImage } from '../../utils/useWorkbenchMediaImage';
|
|
|
6
6
|
import { WorkbenchMediaPlaceholder } from './WorkbenchMediaPlaceholder';
|
|
7
7
|
|
|
8
8
|
export interface WorkbenchMediaSlotProps extends Omit<ComponentPropsWithRef<'span'>, 'children'> {
|
|
9
|
-
alt?: string
|
|
10
|
-
as?: 'div' | 'span'
|
|
11
|
-
fallback?: ReactNode
|
|
12
|
-
fallbackClassName?: string
|
|
13
|
-
fallbackIcon?: string
|
|
9
|
+
alt?: string;
|
|
10
|
+
as?: 'div' | 'span';
|
|
11
|
+
fallback?: ReactNode;
|
|
12
|
+
fallbackClassName?: string;
|
|
13
|
+
fallbackIcon?: string;
|
|
14
14
|
/** Stretch to fill the parent box (hero/cover surfaces). */
|
|
15
|
-
fill?: boolean
|
|
16
|
-
imageClassName?: string
|
|
17
|
-
imageUrl?: string | null
|
|
15
|
+
fill?: boolean;
|
|
16
|
+
imageClassName?: string;
|
|
17
|
+
imageUrl?: string | null;
|
|
18
18
|
/**
|
|
19
19
|
* Native image loading hint. Defaults to `lazy` for list/thumbnail surfaces.
|
|
20
20
|
* Pass `eager` for above-the-fold heroes and detail identity art.
|
|
21
21
|
*/
|
|
22
|
-
loading?: 'eager' | 'lazy'
|
|
22
|
+
loading?: 'eager' | 'lazy';
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export function WorkbenchMediaSlot({
|