@parallelworks/ui 0.70.0 → 0.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/ai/components/ChatSidebar.js +12 -15
- package/dist/ai/components/conversationActions.d.ts +4 -2
- package/dist/ai/components/conversationActions.js +12 -28
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.js +2 -2
- package/dist/ai/ui/sidebar.d.ts +29 -1
- package/dist/ai/ui/sidebar.js +64 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -874,6 +874,14 @@ passes `ChatInput`'s props; `ComposerControls` takes `model` and `allocation`
|
|
|
874
874
|
as a `BoundSetting` for a session that owns its own, and `tools={false}` keeps
|
|
875
875
|
the chat's tools out of a composer they don't apply to.
|
|
876
876
|
|
|
877
|
+
A host's own list of conversations or sessions builds on `ConversationSidebar`
|
|
878
|
+
with the same pieces the chat's list uses: `SidebarRow` with `SidebarRowBody`
|
|
879
|
+
inside its link (an optional `leading` mark such as a status dot, the title
|
|
880
|
+
and time, and an optional `detail` line), `useSessionMenu` for the row menu
|
|
881
|
+
(rename, share, download, then delete apart, each with an optional
|
|
882
|
+
`disabledReason`), `useRowDialogs` for rename and delete, and `SidebarEmpty`
|
|
883
|
+
for an empty list or a failed load.
|
|
884
|
+
|
|
877
885
|
`ChatLayout sidebarMode="auto"` shows the conversation list as a drawer over
|
|
878
886
|
the thread when the chat is narrower than `drawerBelowPx` (`DRAWER_BELOW_PX`, 896, by default),
|
|
879
887
|
measured on the chat's own box; `"drawer"` always does, and `"inline"` (the
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { cx } from "../../cx.js";
|
|
2
2
|
import { ImageIcon, NewChatIcon, UsersIcon } from "../../icons.js";
|
|
3
3
|
import { isPlainClick } from "../../components/AppLink.js";
|
|
4
|
-
import { EmptyState } from "../../components/EmptyState.js";
|
|
5
4
|
import { RelativeTime } from "../../components/relativeTime.js";
|
|
6
5
|
import { SearchInput } from "../../components/SearchInput.js";
|
|
7
6
|
import { useChatConfig } from "../core/config.js";
|
|
8
7
|
import { useChat } from "../core/ChatProvider.js";
|
|
9
8
|
import { ManageProvidersLink } from "./ComposerChrome.js";
|
|
10
9
|
import { FOCUS_SIDEBAR_SEARCH_EVENT } from "../core/events.js";
|
|
11
|
-
import { SidebarRow,
|
|
10
|
+
import { SidebarEmpty, SidebarRow, SidebarRowBody } from "../ui/sidebar.js";
|
|
12
11
|
import { ConversationSidebar } from "../ui/ConversationSidebar.js";
|
|
13
12
|
import { groupConversationsByDate, useConversationActions } from "./conversationActions.js";
|
|
14
13
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -21,25 +20,26 @@ function ConversationRow({ conv, isCurrent, menuItems, openMenu, onOpen }) {
|
|
|
21
20
|
selected: isCurrent,
|
|
22
21
|
menuItems,
|
|
23
22
|
openMenu,
|
|
24
|
-
children: /* @__PURE__ */
|
|
23
|
+
children: /* @__PURE__ */ jsx(LinkComponent, {
|
|
25
24
|
target: {
|
|
26
25
|
kind: "conversation",
|
|
27
26
|
id: conv.id
|
|
28
27
|
},
|
|
29
|
-
className: "flex min-w-0 flex-1
|
|
28
|
+
className: "flex min-w-0 flex-1 py-1 text-left",
|
|
30
29
|
onClick: (e) => {
|
|
31
30
|
if (isPlainClick(e)) onOpen();
|
|
32
31
|
},
|
|
33
|
-
children:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
children: /* @__PURE__ */ jsx(SidebarRowBody, {
|
|
33
|
+
leading: conv.isOwner === false && /* @__PURE__ */ jsx(UsersIcon, {
|
|
34
|
+
className: "h-3 w-3 theme-muted-text",
|
|
35
|
+
title: t.sharedWithYou
|
|
36
|
+
}),
|
|
37
|
+
title: conv.title || t.untitled,
|
|
37
38
|
time: /* @__PURE__ */ jsx(RelativeTime, {
|
|
38
39
|
value: conv.updatedAt ?? conv.createdAt,
|
|
39
40
|
format: "compact"
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
})]
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
43
|
})
|
|
44
44
|
});
|
|
45
45
|
}
|
|
@@ -117,10 +117,7 @@ function ChatSidebar({ actions = true, top }) {
|
|
|
117
117
|
onOpen: closeDrawer
|
|
118
118
|
}),
|
|
119
119
|
loading: isLoading,
|
|
120
|
-
placeholder: /* @__PURE__ */ jsx(
|
|
121
|
-
variant: "bare",
|
|
122
|
-
title: conversations.length === 0 ? tSidebar.noConversations : strings.chrome.noMatches
|
|
123
|
-
}),
|
|
120
|
+
placeholder: /* @__PURE__ */ jsx(SidebarEmpty, { title: conversations.length === 0 ? tSidebar.noConversations : strings.chrome.noMatches }),
|
|
124
121
|
cycle: {
|
|
125
122
|
current: filteredConversations.find((conv) => conv.id === activeConversationId),
|
|
126
123
|
onSelect: (conv) => navigation.toConversation(conv.id)
|
|
@@ -3,10 +3,12 @@ import { type OpenMenu } from '../../components/ContextMenu.js';
|
|
|
3
3
|
import type { MenuEntry } from '../../components/MenuEntries.js';
|
|
4
4
|
import type { ConversationSummary } from '../types.js';
|
|
5
5
|
export type ConversationGroupKey = 'groupToday' | 'groupYesterday' | 'groupThisWeek' | 'groupThisMonth' | 'groupOlder';
|
|
6
|
-
/** Conversations by how long ago they
|
|
7
|
-
* out the groups with none. Each key names its
|
|
6
|
+
/** Conversations by how long ago they last changed, the time each row shows,
|
|
7
|
+
* newest group first, leaving out the groups with none. Each key names its
|
|
8
|
+
* label in the sidebar strings. */
|
|
8
9
|
export declare function groupConversationsByDate<T extends {
|
|
9
10
|
createdAt: string;
|
|
11
|
+
updatedAt?: string | null | undefined;
|
|
10
12
|
}>(conversations: T[]): {
|
|
11
13
|
key: ConversationGroupKey;
|
|
12
14
|
items: T[];
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { DownloadIcon, RenameIcon, ShareIcon, TrashIcon } from "../../icons.js";
|
|
2
1
|
import { toast } from "../../components/Toast.js";
|
|
3
2
|
import { useStrings } from "../../components/Provider.js";
|
|
4
3
|
import { useContextMenu } from "../../components/ContextMenu.js";
|
|
5
4
|
import { useChatConfig } from "../core/config.js";
|
|
6
5
|
import { useChat } from "../core/ChatProvider.js";
|
|
7
|
-
import { useRowDialogs } from "../ui/sidebar.js";
|
|
6
|
+
import { useRowDialogs, useSessionMenu } from "../ui/sidebar.js";
|
|
8
7
|
import { conversationToMarkdown, downloadText, exportFilename } from "../core/exportConversation.js";
|
|
9
8
|
import ShareDialog from "./ShareDialog.js";
|
|
10
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
10
|
import { useState } from "react";
|
|
12
11
|
import { DateTime } from "luxon";
|
|
13
12
|
//#region src/ai/components/conversationActions.tsx
|
|
14
|
-
/** Conversations by how long ago they
|
|
15
|
-
* out the groups with none. Each key names its
|
|
13
|
+
/** Conversations by how long ago they last changed, the time each row shows,
|
|
14
|
+
* newest group first, leaving out the groups with none. Each key names its
|
|
15
|
+
* label in the sidebar strings. */
|
|
16
16
|
function groupConversationsByDate(conversations) {
|
|
17
17
|
const now = DateTime.now();
|
|
18
18
|
const groups = {
|
|
@@ -23,7 +23,7 @@ function groupConversationsByDate(conversations) {
|
|
|
23
23
|
groupOlder: []
|
|
24
24
|
};
|
|
25
25
|
for (const conv of conversations) {
|
|
26
|
-
const days = now.diff(DateTime.fromISO(conv.createdAt), "days").days;
|
|
26
|
+
const days = now.diff(DateTime.fromISO(conv.updatedAt ?? conv.createdAt), "days").days;
|
|
27
27
|
groups[days < 1 ? "groupToday" : days < 2 ? "groupYesterday" : days < 7 ? "groupThisWeek" : days < 30 ? "groupThisMonth" : "groupOlder"].push(conv);
|
|
28
28
|
}
|
|
29
29
|
return Object.entries(groups).filter(([, items]) => items.length > 0).map(([key, items]) => ({
|
|
@@ -63,29 +63,13 @@ function useConversationActions() {
|
|
|
63
63
|
toast.error(strings.chrome.exportError);
|
|
64
64
|
}
|
|
65
65
|
};
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
label: common.share,
|
|
74
|
-
icon: /* @__PURE__ */ jsx(ShareIcon, {}),
|
|
75
|
-
onClick: () => setSharing(conv.id)
|
|
76
|
-
}] : [],
|
|
77
|
-
{
|
|
78
|
-
label: common.download,
|
|
79
|
-
icon: /* @__PURE__ */ jsx(DownloadIcon, {}),
|
|
80
|
-
onClick: () => void download(conv.id)
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
label: common.delete,
|
|
84
|
-
icon: /* @__PURE__ */ jsx(TrashIcon, {}),
|
|
85
|
-
destructive: true,
|
|
86
|
-
onClick: () => requestDelete(conv)
|
|
87
|
-
}
|
|
88
|
-
];
|
|
66
|
+
const sessionMenu = useSessionMenu();
|
|
67
|
+
const menuItems = (conv) => sessionMenu({
|
|
68
|
+
rename: { onClick: () => requestRename(conv) },
|
|
69
|
+
share: adapter.sharing && conv.isOwner !== false ? { onClick: () => setSharing(conv.id) } : void 0,
|
|
70
|
+
download: { onClick: () => void download(conv.id) },
|
|
71
|
+
remove: { onClick: () => requestDelete(conv) }
|
|
72
|
+
});
|
|
89
73
|
return {
|
|
90
74
|
menuItems,
|
|
91
75
|
openMenu,
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -42,5 +42,5 @@ export { type ChatStrings, defaultChatStrings } from './strings.js';
|
|
|
42
42
|
export * from './types.js';
|
|
43
43
|
export { ConversationSidebar, type ConversationSidebarGroup, sidebarDrawerProps, } from './ui/ConversationSidebar.js';
|
|
44
44
|
export { NoticeBar, NoticeCard, type NoticeTone, OutputCard } from './ui/Notice.js';
|
|
45
|
-
export { RenameDialog, type RowDialogStrings, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowTitle, SidebarToggle, useRowDialogs, } from './ui/sidebar.js';
|
|
45
|
+
export { RenameDialog, type RowDialogStrings, type SessionMenuAction, SidebarEmpty, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowBody, SidebarRowTitle, SidebarToggle, useRowDialogs, useSessionMenu, } from './ui/sidebar.js';
|
|
46
46
|
export { isMac, isOrgModel } from './utils.js';
|
package/dist/ai/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import ChatEmptyState from "./components/ChatEmptyState.js";
|
|
|
35
35
|
import { FOCUS_SIDEBAR_SEARCH_EVENT } from "./core/events.js";
|
|
36
36
|
import { useKeyboardShortcuts } from "./core/useKeyboardShortcuts.js";
|
|
37
37
|
import { KeyboardShortcutsProvider } from "./core/KeyboardShortcutsProvider.js";
|
|
38
|
-
import { RenameDialog, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowTitle, SidebarToggle, useRowDialogs } from "./ui/sidebar.js";
|
|
38
|
+
import { RenameDialog, SidebarEmpty, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowBody, SidebarRowTitle, SidebarToggle, useRowDialogs, useSessionMenu } from "./ui/sidebar.js";
|
|
39
39
|
import { ConversationSidebar, sidebarDrawerProps } from "./ui/ConversationSidebar.js";
|
|
40
40
|
import ShareDialog, { ShareButton } from "./components/ShareDialog.js";
|
|
41
41
|
import { groupConversationsByDate, useConversationActions } from "./components/conversationActions.js";
|
|
@@ -46,4 +46,4 @@ import ChatMessageList from "./components/ChatMessageList.js";
|
|
|
46
46
|
import SessionView from "./components/SessionView.js";
|
|
47
47
|
import ChatThread from "./components/ChatThread.js";
|
|
48
48
|
import { NoticeBar, NoticeCard, OutputCard } from "./ui/Notice.js";
|
|
49
|
-
export { AGENT_COLOR_NAMES, ActivityLine, AgentMessageParts, AllocationSelector, ApprovalBlock, AttachmentManager, AttachmentUpload, BlockedGroupBanner, BranchNavigator, CHAT_COLUMN_SCOPE, ChatAdapterError, ChatEmptyState, ChatInput, ChatLayout, ChatMessageList, ChatMessage_default as ChatMessageView, ChatProvider, ChatSidebar, ChatStage, ChatThread, ComposerContext, ComposerControls, ComposerSettings, ComposerUsage, ConnectToolsLink, ConversationLayout, ConversationSidebar, DEFAULT_PERMISSION_MODE, DRAWER_BELOW_PX, DragOverlay, FOCUS_SIDEBAR_SEARCH_EVENT, INTERRUPTED_NOTICE, KeyboardShortcutsProvider, MAX_EDIT_DIFF_LINES, MAX_WRITE_DIFF_LINES, ManageProvidersLink, ModelSelector, NAMED_PERMISSION_MODES, NoticeBar, NoticeCard, OutputCard, PermissionPicker, ProviderIssueBanner, RenameDialog, SessionView, ShareButton, ShareDialog, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowTitle, SidebarToggle, agentColorHex, agentTypeLabel, applyPartDelta, askQuestionFromArgs, bashExitCode, chatReducer, clampPermissionMode, classifyPseudoUserMessage, clip, computeEditDiff, computeWriteRows, defaultChatStrings, defaultToolStrings, editSummary, finalizeParts, firstNonEmptyLine, fullToolArgs, getGreeting, getProviderKeyFromModelId, groupConversationsByDate, hiddenTranscriptTool, initialState, interruptionNotice, isEditDiffTool, isGroupableTool, isMac, isNamedPermissionMode, isOrgModel, languageForPath, lineDelta, parseEditArgs, parseSubagentNotice, pasteInlineMaxBytes, permissionModesUpTo, planFromArgs, providerIssueFor, resolveChatConfig, resultFailed, rollupSentence, sanitizeLabel, sanitizePanelText, sidebarDrawerProps, slashMatches, subagentDeliveryLine, summarizeToolArgs, taskCallFromArgs, thinkingHeading, tokenizeDiffLines, toolHeaderFor, toolSummary, useChat, useChatConfig, useChatStream, useConversationActions, useDragDrop, useKeyboardShortcuts, useRowDialogs, wordEmphasisRanges };
|
|
49
|
+
export { AGENT_COLOR_NAMES, ActivityLine, AgentMessageParts, AllocationSelector, ApprovalBlock, AttachmentManager, AttachmentUpload, BlockedGroupBanner, BranchNavigator, CHAT_COLUMN_SCOPE, ChatAdapterError, ChatEmptyState, ChatInput, ChatLayout, ChatMessageList, ChatMessage_default as ChatMessageView, ChatProvider, ChatSidebar, ChatStage, ChatThread, ComposerContext, ComposerControls, ComposerSettings, ComposerUsage, ConnectToolsLink, ConversationLayout, ConversationSidebar, DEFAULT_PERMISSION_MODE, DRAWER_BELOW_PX, DragOverlay, FOCUS_SIDEBAR_SEARCH_EVENT, INTERRUPTED_NOTICE, KeyboardShortcutsProvider, MAX_EDIT_DIFF_LINES, MAX_WRITE_DIFF_LINES, ManageProvidersLink, ModelSelector, NAMED_PERMISSION_MODES, NoticeBar, NoticeCard, OutputCard, PermissionPicker, ProviderIssueBanner, RenameDialog, SessionView, ShareButton, ShareDialog, SidebarEmpty, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowBody, SidebarRowTitle, SidebarToggle, agentColorHex, agentTypeLabel, applyPartDelta, askQuestionFromArgs, bashExitCode, chatReducer, clampPermissionMode, classifyPseudoUserMessage, clip, computeEditDiff, computeWriteRows, defaultChatStrings, defaultToolStrings, editSummary, finalizeParts, firstNonEmptyLine, fullToolArgs, getGreeting, getProviderKeyFromModelId, groupConversationsByDate, hiddenTranscriptTool, initialState, interruptionNotice, isEditDiffTool, isGroupableTool, isMac, isNamedPermissionMode, isOrgModel, languageForPath, lineDelta, parseEditArgs, parseSubagentNotice, pasteInlineMaxBytes, permissionModesUpTo, planFromArgs, providerIssueFor, resolveChatConfig, resultFailed, rollupSentence, sanitizeLabel, sanitizePanelText, sidebarDrawerProps, slashMatches, subagentDeliveryLine, summarizeToolArgs, taskCallFromArgs, thinkingHeading, tokenizeDiffLines, toolHeaderFor, toolSummary, useChat, useChatConfig, useChatStream, useConversationActions, useDragDrop, useKeyboardShortcuts, useRowDialogs, useSessionMenu, wordEmphasisRanges };
|
package/dist/ai/ui/sidebar.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
2
|
import type { OpenMenu } from '../../components/ContextMenu.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type MenuEntry } from '../../components/MenuEntries.js';
|
|
4
4
|
export declare const SIDEBAR_DEFAULT_WIDTH_PX = 256;
|
|
5
5
|
/** The column a conversation list lives in: it animates between its width
|
|
6
6
|
* and a rail, unless a drag is setting the width right now. */
|
|
@@ -34,6 +34,34 @@ export declare function SidebarRowTitle({ children, time, }: {
|
|
|
34
34
|
/** When it last changed, short: a compact `RelativeTime`. */
|
|
35
35
|
time?: ReactNode;
|
|
36
36
|
}): import("react").JSX.Element;
|
|
37
|
+
/** A row's content: an optional mark before it (a status dot, a shared
|
|
38
|
+
* icon), the title with its time, and an optional line under it for what the
|
|
39
|
+
* mark cannot say, such as the machine or a state that needs the reader. */
|
|
40
|
+
export declare function SidebarRowBody({ leading, title, time, detail, }: {
|
|
41
|
+
leading?: ReactNode;
|
|
42
|
+
title: ReactNode;
|
|
43
|
+
time?: ReactNode;
|
|
44
|
+
detail?: ReactNode;
|
|
45
|
+
}): import("react").JSX.Element;
|
|
46
|
+
/** An action a row's menu offers, and why it is unavailable when it is. */
|
|
47
|
+
export interface SessionMenuAction {
|
|
48
|
+
onClick: () => void;
|
|
49
|
+
disabledReason?: string | undefined;
|
|
50
|
+
}
|
|
51
|
+
/** A row's menu in one order wherever a list of conversations or sessions
|
|
52
|
+
* shows: rename, share, download, then delete apart. Each is left out unless given. */
|
|
53
|
+
export declare function useSessionMenu(): (actions: {
|
|
54
|
+
rename?: SessionMenuAction | undefined;
|
|
55
|
+
share?: SessionMenuAction | undefined;
|
|
56
|
+
download?: SessionMenuAction | undefined;
|
|
57
|
+
remove?: SessionMenuAction | undefined;
|
|
58
|
+
}) => MenuEntry[];
|
|
59
|
+
/** In place of a list with nothing to show: none yet, nothing matching, or
|
|
60
|
+
* why it could not load. */
|
|
61
|
+
export declare function SidebarEmpty({ title, error }: {
|
|
62
|
+
title: string;
|
|
63
|
+
error?: string | undefined;
|
|
64
|
+
}): import("react").JSX.Element;
|
|
37
65
|
/** One entry in the list: the row highlights while it is the open one or
|
|
38
66
|
* while its menu is up, and the menu opens from its button or a right-click. */
|
|
39
67
|
export declare function SidebarRow({ selected, menuItems, openMenu, className, children, }: {
|
package/dist/ai/ui/sidebar.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { cx } from "../../cx.js";
|
|
2
|
-
import { SidebarIcon } from "../../icons.js";
|
|
2
|
+
import { DownloadIcon, RenameIcon, ShareIcon, SidebarIcon, TrashIcon } from "../../icons.js";
|
|
3
3
|
import { Tooltip } from "../../components/Tooltip.js";
|
|
4
|
+
import { useStrings } from "../../components/Provider.js";
|
|
4
5
|
import { AppLink, isPlainClick } from "../../components/AppLink.js";
|
|
6
|
+
import { EmptyState } from "../../components/EmptyState.js";
|
|
7
|
+
import { menuDivider } from "../../components/MenuEntries.js";
|
|
5
8
|
import { IconButton } from "../../components/IconButton.js";
|
|
6
9
|
import { fieldBox } from "../../components/fieldBox.js";
|
|
7
10
|
import { focusOnMount } from "../../components/focus.js";
|
|
@@ -56,6 +59,65 @@ function SidebarRowTitle({ children, time }) {
|
|
|
56
59
|
})]
|
|
57
60
|
});
|
|
58
61
|
}
|
|
62
|
+
/** A row's content: an optional mark before it (a status dot, a shared
|
|
63
|
+
* icon), the title with its time, and an optional line under it for what the
|
|
64
|
+
* mark cannot say, such as the machine or a state that needs the reader. */
|
|
65
|
+
function SidebarRowBody({ leading, title, time, detail }) {
|
|
66
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
67
|
+
className: "flex min-w-0 flex-1 items-start gap-2",
|
|
68
|
+
children: [leading && /* @__PURE__ */ jsx("span", {
|
|
69
|
+
className: "mt-1 flex h-3 shrink-0 items-center",
|
|
70
|
+
children: leading
|
|
71
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
72
|
+
className: "min-w-0 flex-1",
|
|
73
|
+
children: [/* @__PURE__ */ jsx(SidebarRowTitle, {
|
|
74
|
+
time,
|
|
75
|
+
children: title
|
|
76
|
+
}), detail && /* @__PURE__ */ jsx("span", {
|
|
77
|
+
className: "mt-0.5 flex min-w-0 items-center gap-1.5 text-[11px]",
|
|
78
|
+
children: detail
|
|
79
|
+
})]
|
|
80
|
+
})]
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/** A row's menu in one order wherever a list of conversations or sessions
|
|
84
|
+
* shows: rename, share, download, then delete apart. Each is left out unless given. */
|
|
85
|
+
function useSessionMenu() {
|
|
86
|
+
const { common } = useStrings();
|
|
87
|
+
return ({ rename, share, download, remove }) => {
|
|
88
|
+
const entry = (label, icon, action) => ({
|
|
89
|
+
label,
|
|
90
|
+
icon,
|
|
91
|
+
onClick: action.onClick,
|
|
92
|
+
...action.disabledReason ? {
|
|
93
|
+
disabled: true,
|
|
94
|
+
disabledReason: action.disabledReason
|
|
95
|
+
} : {}
|
|
96
|
+
});
|
|
97
|
+
const items = [
|
|
98
|
+
...rename ? [entry(common.rename, /* @__PURE__ */ jsx(RenameIcon, {}), rename)] : [],
|
|
99
|
+
...share ? [entry(common.share, /* @__PURE__ */ jsx(ShareIcon, {}), share)] : [],
|
|
100
|
+
...download ? [entry(common.download, /* @__PURE__ */ jsx(DownloadIcon, {}), download)] : []
|
|
101
|
+
];
|
|
102
|
+
if (remove) {
|
|
103
|
+
if (items.length > 0) items.push(menuDivider);
|
|
104
|
+
items.push({
|
|
105
|
+
...entry(common.delete, /* @__PURE__ */ jsx(TrashIcon, {}), remove),
|
|
106
|
+
destructive: true
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return items;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/** In place of a list with nothing to show: none yet, nothing matching, or
|
|
113
|
+
* why it could not load. */
|
|
114
|
+
function SidebarEmpty({ title, error }) {
|
|
115
|
+
return /* @__PURE__ */ jsx(EmptyState, {
|
|
116
|
+
variant: "bare",
|
|
117
|
+
title: error ?? title,
|
|
118
|
+
...error ? { testId: "sidebar-list-error" } : {}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
59
121
|
/** One entry in the list: the row highlights while it is the open one or
|
|
60
122
|
* while its menu is up, and the menu opens from its button or a right-click. */
|
|
61
123
|
function SidebarRow({ selected, menuItems, openMenu, className, children }) {
|
|
@@ -176,4 +238,4 @@ function useRowDialogs({ strings, nameOf, onDelete, onRename }) {
|
|
|
176
238
|
};
|
|
177
239
|
}
|
|
178
240
|
//#endregion
|
|
179
|
-
export { RenameDialog, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowTitle, SidebarToggle, useRowDialogs };
|
|
241
|
+
export { RenameDialog, SidebarEmpty, SidebarGroupHeading, SidebarPanel, SidebarRailItem, SidebarRow, SidebarRowBody, SidebarRowTitle, SidebarToggle, useRowDialogs, useSessionMenu };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parallelworks/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.0",
|
|
4
4
|
"description": "React UI components: a theme contract, icons, brand logos, primitives, lists, forms, a job graph, a code editor, a log viewer, a file explorer and an AI chat, each on its own subpath",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|