@datum-cloud/datum-ui 2.9.1 → 2.10.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/dist/assistant/index.mjs +133 -24
- package/dist/components/features/assistant/components/assistant-workspace.d.ts +11 -1
- package/dist/components/features/assistant/components/sidebar/history-panel.d.ts +16 -3
- package/dist/components/features/assistant/types.d.ts +5 -0
- package/package.json +1 -1
package/dist/assistant/index.mjs
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { t as cn } from "../utils-Bu32wN-x.mjs";
|
|
2
|
+
import { t as Button } from "../button-DoMqfQLu.mjs";
|
|
2
3
|
import { t as Icon } from "../icon-wrapper-DKfJlJd0.mjs";
|
|
4
|
+
import { t as Dialog } from "../dialog-Gu70fban.mjs";
|
|
3
5
|
import { a as DropdownMenuRadioGroup, c as DropdownMenuTrigger, i as DropdownMenuLabel, o as DropdownMenuRadioItem, r as DropdownMenuContent, s as DropdownMenuSeparator, t as DropdownMenu } from "../dropdown-menu-b8zY5Cs6.mjs";
|
|
4
6
|
import { t as Tooltip } from "../tooltip-DhbN1BDK.mjs";
|
|
5
7
|
import { n as EASE, t as DURATION } from "../motion-DvGRWdsm.mjs";
|
|
6
|
-
import { ArrowDown, ArrowRight, ArrowUp, Brain, Check, ChevronDown, Copy, Download, MessagesSquare, Mic, MicOff, PanelLeft, Plus, RotateCw, Square, Trash2 } from "lucide-react";
|
|
8
|
+
import { Archive, ArchiveRestore, ArrowDown, ArrowRight, ArrowUp, Brain, Check, ChevronDown, Copy, Download, MessagesSquare, Mic, MicOff, PanelLeft, Plus, RotateCw, Square, Trash2 } from "lucide-react";
|
|
7
9
|
import { Fragment, createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
|
|
8
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
11
|
import { AnimatePresence, motion } from "motion/react";
|
|
@@ -842,12 +844,32 @@ function downloadChat(chat) {
|
|
|
842
844
|
a.click();
|
|
843
845
|
URL.revokeObjectURL(url);
|
|
844
846
|
}
|
|
845
|
-
|
|
847
|
+
const ROW_ACTION_CLASS = "text-muted-foreground/40 shrink-0 rounded p-0.5 opacity-0 transition-colors group-hover:opacity-100";
|
|
848
|
+
function HistoryPanel({ chatList, currentChatId, onLoadChat, onDeleteChat, onArchiveChat, onUnarchiveChat, confirmDelete = false, header }) {
|
|
849
|
+
const archiveEnabled = Boolean(onArchiveChat);
|
|
846
850
|
const [query, setQuery] = useState("");
|
|
851
|
+
const [showArchived, setShowArchived] = useState(false);
|
|
852
|
+
const [pendingDelete, setPendingDelete] = useState(null);
|
|
853
|
+
const inArchivedView = archiveEnabled && showArchived;
|
|
847
854
|
const filtered = useMemo(() => {
|
|
855
|
+
const inView = archiveEnabled ? chatList.filter((c) => Boolean(c.archived) === showArchived) : chatList;
|
|
848
856
|
const q = query.trim().toLowerCase();
|
|
849
|
-
return q ?
|
|
850
|
-
}, [
|
|
857
|
+
return q ? inView.filter((c) => c.title.toLowerCase().includes(q)) : inView;
|
|
858
|
+
}, [
|
|
859
|
+
archiveEnabled,
|
|
860
|
+
chatList,
|
|
861
|
+
query,
|
|
862
|
+
showArchived
|
|
863
|
+
]);
|
|
864
|
+
const emptyText = inArchivedView ? query ? "No matching archived chats" : "No archived chats" : query ? "No matching chats" : "No saved chats";
|
|
865
|
+
const handleDelete = (e, chat) => {
|
|
866
|
+
if (!confirmDelete) {
|
|
867
|
+
onDeleteChat(e, chat.id);
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
e.stopPropagation();
|
|
871
|
+
setPendingDelete(chat);
|
|
872
|
+
};
|
|
851
873
|
return /* @__PURE__ */ jsxs("div", {
|
|
852
874
|
className: "bg-background flex h-full w-64 shrink-0 flex-col border-r",
|
|
853
875
|
children: [
|
|
@@ -855,36 +877,90 @@ function HistoryPanel({ chatList, currentChatId, onLoadChat, onDeleteChat, heade
|
|
|
855
877
|
className: "shrink-0 border-b px-3 py-2",
|
|
856
878
|
children: header
|
|
857
879
|
}),
|
|
858
|
-
/* @__PURE__ */
|
|
859
|
-
className: "flex h-12 items-center border-b px-2",
|
|
860
|
-
children: /* @__PURE__ */ jsx("input", {
|
|
880
|
+
/* @__PURE__ */ jsxs("div", {
|
|
881
|
+
className: "flex h-12 items-center gap-1 border-b px-2",
|
|
882
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
861
883
|
value: query,
|
|
862
884
|
onChange: (e) => setQuery(e.target.value),
|
|
863
|
-
placeholder: "Search chats…",
|
|
885
|
+
placeholder: inArchivedView ? "Search archived chats…" : "Search chats…",
|
|
864
886
|
className: "bg-muted text-foreground placeholder:text-muted-foreground/70 focus:ring-primary/40 w-full rounded-md px-2.5 py-1.5 text-xs focus:ring-1 focus:outline-none"
|
|
865
|
-
})
|
|
887
|
+
}), archiveEnabled && /* @__PURE__ */ jsx(Tooltip, {
|
|
888
|
+
message: showArchived ? "Show active chats" : "Show archived chats",
|
|
889
|
+
side: "bottom",
|
|
890
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
891
|
+
type: "button",
|
|
892
|
+
"aria-label": "Archived",
|
|
893
|
+
"aria-pressed": showArchived,
|
|
894
|
+
onClick: () => setShowArchived((v) => !v),
|
|
895
|
+
className: cn("shrink-0 rounded-md p-1.5 transition-colors", showArchived ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground hover:bg-accent"),
|
|
896
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
897
|
+
icon: Archive,
|
|
898
|
+
className: "size-3.5"
|
|
899
|
+
})
|
|
900
|
+
})
|
|
901
|
+
})]
|
|
866
902
|
}),
|
|
867
903
|
/* @__PURE__ */ jsx("div", {
|
|
868
904
|
className: "flex flex-1 flex-col gap-0.5 overflow-y-auto p-2",
|
|
869
905
|
children: filtered.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
870
906
|
className: "text-muted-foreground/60 px-2 py-1 text-xs",
|
|
871
|
-
children:
|
|
907
|
+
children: emptyText
|
|
872
908
|
}) : filtered.map((chat) => /* @__PURE__ */ jsxs("button", {
|
|
873
909
|
type: "button",
|
|
874
910
|
onClick: () => onLoadChat(chat),
|
|
875
911
|
className: cn("group w-full rounded-lg px-2 py-1.5 text-left transition-colors", chat.id === currentChatId ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground hover:bg-accent/50"),
|
|
876
912
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
877
913
|
className: "flex items-center gap-1",
|
|
878
|
-
children: [
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
914
|
+
children: [
|
|
915
|
+
/* @__PURE__ */ jsx("span", {
|
|
916
|
+
className: "min-w-0 flex-1 truncate text-xs font-medium",
|
|
917
|
+
children: chat.title
|
|
918
|
+
}),
|
|
919
|
+
archiveEnabled && !inArchivedView && /* @__PURE__ */ jsx(Tooltip, {
|
|
920
|
+
message: "Archive chat",
|
|
921
|
+
side: "top",
|
|
922
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
923
|
+
role: "button",
|
|
924
|
+
onClick: (e) => {
|
|
925
|
+
e.stopPropagation();
|
|
926
|
+
onArchiveChat?.(e, chat.id);
|
|
927
|
+
},
|
|
928
|
+
"aria-label": "Archive chat",
|
|
929
|
+
className: cn(ROW_ACTION_CLASS, "hover:text-foreground"),
|
|
930
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
931
|
+
icon: Archive,
|
|
932
|
+
className: "size-3"
|
|
933
|
+
})
|
|
934
|
+
})
|
|
935
|
+
}),
|
|
936
|
+
inArchivedView && onUnarchiveChat && /* @__PURE__ */ jsx(Tooltip, {
|
|
937
|
+
message: "Unarchive chat",
|
|
938
|
+
side: "top",
|
|
939
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
940
|
+
role: "button",
|
|
941
|
+
onClick: (e) => {
|
|
942
|
+
e.stopPropagation();
|
|
943
|
+
onUnarchiveChat(e, chat.id);
|
|
944
|
+
},
|
|
945
|
+
"aria-label": "Unarchive chat",
|
|
946
|
+
className: cn(ROW_ACTION_CLASS, "hover:text-foreground"),
|
|
947
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
948
|
+
icon: ArchiveRestore,
|
|
949
|
+
className: "size-3"
|
|
950
|
+
})
|
|
951
|
+
})
|
|
952
|
+
}),
|
|
953
|
+
/* @__PURE__ */ jsx("span", {
|
|
954
|
+
role: "button",
|
|
955
|
+
onClick: (e) => handleDelete(e, chat),
|
|
956
|
+
"aria-label": "Delete chat",
|
|
957
|
+
className: cn(ROW_ACTION_CLASS, "hover:text-destructive"),
|
|
958
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
959
|
+
icon: Trash2,
|
|
960
|
+
className: "size-3"
|
|
961
|
+
})
|
|
962
|
+
})
|
|
963
|
+
]
|
|
888
964
|
}), /* @__PURE__ */ jsxs("span", {
|
|
889
965
|
className: "flex items-center gap-1",
|
|
890
966
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -900,8 +976,11 @@ function HistoryPanel({ chatList, currentChatId, onLoadChat, onDeleteChat, heade
|
|
|
900
976
|
downloadChat(chat);
|
|
901
977
|
},
|
|
902
978
|
"aria-label": "Download chat as Markdown",
|
|
903
|
-
className: "
|
|
904
|
-
children: /* @__PURE__ */ jsx(
|
|
979
|
+
className: cn(ROW_ACTION_CLASS, "hover:text-foreground"),
|
|
980
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
981
|
+
icon: Download,
|
|
982
|
+
className: "size-3"
|
|
983
|
+
})
|
|
905
984
|
})
|
|
906
985
|
})]
|
|
907
986
|
})]
|
|
@@ -910,13 +989,40 @@ function HistoryPanel({ chatList, currentChatId, onLoadChat, onDeleteChat, heade
|
|
|
910
989
|
/* @__PURE__ */ jsx("p", {
|
|
911
990
|
className: "text-muted-foreground mt-auto shrink-0 border-t px-3 py-2 text-[10px]",
|
|
912
991
|
children: "Chats are saved to your browser's local storage."
|
|
992
|
+
}),
|
|
993
|
+
confirmDelete && /* @__PURE__ */ jsx(Dialog, {
|
|
994
|
+
open: pendingDelete !== null,
|
|
995
|
+
onOpenChange: (open) => !open && setPendingDelete(null),
|
|
996
|
+
children: /* @__PURE__ */ jsxs(Dialog.Content, {
|
|
997
|
+
className: "sm:max-w-md",
|
|
998
|
+
children: [/* @__PURE__ */ jsx(Dialog.Header, {
|
|
999
|
+
title: "Delete chat?",
|
|
1000
|
+
description: pendingDelete ? `"${pendingDelete.title}" will be permanently deleted. This can't be undone.` : void 0
|
|
1001
|
+
}), /* @__PURE__ */ jsxs(Dialog.Footer, {
|
|
1002
|
+
className: "border-t-0",
|
|
1003
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
1004
|
+
type: "tertiary",
|
|
1005
|
+
theme: "outline",
|
|
1006
|
+
onClick: () => setPendingDelete(null),
|
|
1007
|
+
children: "Cancel"
|
|
1008
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
1009
|
+
type: "danger",
|
|
1010
|
+
theme: "solid",
|
|
1011
|
+
onClick: (e) => {
|
|
1012
|
+
if (pendingDelete) onDeleteChat(e, pendingDelete.id);
|
|
1013
|
+
setPendingDelete(null);
|
|
1014
|
+
},
|
|
1015
|
+
children: "Delete"
|
|
1016
|
+
})]
|
|
1017
|
+
})]
|
|
1018
|
+
})
|
|
913
1019
|
})
|
|
914
1020
|
]
|
|
915
1021
|
});
|
|
916
1022
|
}
|
|
917
1023
|
//#endregion
|
|
918
1024
|
//#region src/components/features/assistant/components/assistant-workspace.tsx
|
|
919
|
-
function AssistantWorkspace({ config, userName, title, messages, status, error, isReady, chatList, currentChatId, sidebarHeader, editor, htmlByUserMsgIndex, bottomRef, containerRef, userScrolledUpRef, onSend, onStop, onRetry, onNewChat, onLoadChat, onDeleteChat, onSuggestion, modelId, effortId, onModelChange, onEffortChange, micSupported, micListening, micFrequencyData, onMicToggle, historyOpen, onToggleHistory }) {
|
|
1025
|
+
function AssistantWorkspace({ config, userName, title, messages, status, error, isReady, chatList, currentChatId, sidebarHeader, editor, htmlByUserMsgIndex, bottomRef, containerRef, userScrolledUpRef, onSend, onStop, onRetry, onNewChat, onLoadChat, onDeleteChat, onArchiveChat, onUnarchiveChat, confirmDelete, onSuggestion, modelId, effortId, onModelChange, onEffortChange, micSupported, micListening, micFrequencyData, onMicToggle, historyOpen, onToggleHistory }) {
|
|
920
1026
|
const hasMessages = messages.length > 0;
|
|
921
1027
|
const promptCard = /* @__PURE__ */ jsx(PromptCard, {
|
|
922
1028
|
editor,
|
|
@@ -961,7 +1067,10 @@ function AssistantWorkspace({ config, userName, title, messages, status, error,
|
|
|
961
1067
|
currentChatId,
|
|
962
1068
|
header: sidebarHeader,
|
|
963
1069
|
onLoadChat,
|
|
964
|
-
onDeleteChat
|
|
1070
|
+
onDeleteChat,
|
|
1071
|
+
onArchiveChat,
|
|
1072
|
+
onUnarchiveChat,
|
|
1073
|
+
confirmDelete
|
|
965
1074
|
})
|
|
966
1075
|
})
|
|
967
1076
|
}),
|
|
@@ -38,6 +38,16 @@ export interface AssistantWorkspaceProps {
|
|
|
38
38
|
onNewChat: () => void;
|
|
39
39
|
onLoadChat: (chat: ChatSummary) => void;
|
|
40
40
|
onDeleteChat: (e: ReactMouseEvent, chatId: string) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Opt-in archive support. When provided, `chatList` may mix archived and
|
|
43
|
+
* active chats; the history panel lists active chats by default and adds an
|
|
44
|
+
* "Archived" view toggle plus per-row archive actions.
|
|
45
|
+
*/
|
|
46
|
+
onArchiveChat?: (e: ReactMouseEvent, chatId: string) => void;
|
|
47
|
+
/** Restores an archived chat from the history panel's archived view. */
|
|
48
|
+
onUnarchiveChat?: (e: ReactMouseEvent, chatId: string) => void;
|
|
49
|
+
/** Confirm (deletion can't be undone) before calling `onDeleteChat`. */
|
|
50
|
+
confirmDelete?: boolean;
|
|
41
51
|
onSuggestion: (text: string) => void;
|
|
42
52
|
modelId: string;
|
|
43
53
|
effortId: EffortId;
|
|
@@ -50,4 +60,4 @@ export interface AssistantWorkspaceProps {
|
|
|
50
60
|
historyOpen: boolean;
|
|
51
61
|
onToggleHistory: () => void;
|
|
52
62
|
}
|
|
53
|
-
export declare function AssistantWorkspace({ config, userName, title, messages, status, error, isReady, chatList, currentChatId, sidebarHeader, editor, htmlByUserMsgIndex, bottomRef, containerRef, userScrolledUpRef, onSend, onStop, onRetry, onNewChat, onLoadChat, onDeleteChat, onSuggestion, modelId, effortId, onModelChange, onEffortChange, micSupported, micListening, micFrequencyData, onMicToggle, historyOpen, onToggleHistory, }: AssistantWorkspaceProps): import("react").JSX.Element;
|
|
63
|
+
export declare function AssistantWorkspace({ config, userName, title, messages, status, error, isReady, chatList, currentChatId, sidebarHeader, editor, htmlByUserMsgIndex, bottomRef, containerRef, userScrolledUpRef, onSend, onStop, onRetry, onNewChat, onLoadChat, onDeleteChat, onArchiveChat, onUnarchiveChat, confirmDelete, onSuggestion, modelId, effortId, onModelChange, onEffortChange, micSupported, micListening, micFrequencyData, onMicToggle, historyOpen, onToggleHistory, }: AssistantWorkspaceProps): import("react").JSX.Element;
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { ChatSummary } from '../../types';
|
|
3
|
-
interface HistoryPanelProps {
|
|
3
|
+
export interface HistoryPanelProps {
|
|
4
4
|
chatList: ChatSummary[];
|
|
5
5
|
currentChatId: string;
|
|
6
6
|
onLoadChat: (chat: ChatSummary) => void;
|
|
7
7
|
onDeleteChat: (e: React.MouseEvent, chatId: string) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Opt-in archive support. When provided, `chatList` may mix archived and
|
|
10
|
+
* active chats: the panel lists active chats by default, adds an "Archived"
|
|
11
|
+
* view toggle next to the search input, and gives active rows an archive
|
|
12
|
+
* action. When omitted, the `archived` flag is ignored and no archive UI renders.
|
|
13
|
+
*/
|
|
14
|
+
onArchiveChat?: (e: React.MouseEvent, chatId: string) => void;
|
|
15
|
+
/** Restores an archived chat. Rendered on rows in the archived view. */
|
|
16
|
+
onUnarchiveChat?: (e: React.MouseEvent, chatId: string) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Ask for confirmation (deletion can't be undone) before calling
|
|
19
|
+
* `onDeleteChat`. Defaults to false, which deletes immediately.
|
|
20
|
+
*/
|
|
21
|
+
confirmDelete?: boolean;
|
|
8
22
|
/**
|
|
9
23
|
* Optional host-supplied block pinned above the search input, naming the scope
|
|
10
24
|
* the listed chats belong to — cloud-portal shows the current project. Hosts
|
|
@@ -12,5 +26,4 @@ interface HistoryPanelProps {
|
|
|
12
26
|
*/
|
|
13
27
|
header?: ReactNode;
|
|
14
28
|
}
|
|
15
|
-
export declare function HistoryPanel({ chatList, currentChatId, onLoadChat, onDeleteChat, header, }: HistoryPanelProps): import("react").JSX.Element;
|
|
16
|
-
export {};
|
|
29
|
+
export declare function HistoryPanel({ chatList, currentChatId, onLoadChat, onDeleteChat, onArchiveChat, onUnarchiveChat, confirmDelete, header, }: HistoryPanelProps): import("react").JSX.Element;
|
|
@@ -63,4 +63,9 @@ export interface ChatSummary {
|
|
|
63
63
|
title: string;
|
|
64
64
|
updatedAt: number;
|
|
65
65
|
messages: UIMessage[];
|
|
66
|
+
/**
|
|
67
|
+
* Archived (hidden but restorable). Only honoured when the host passes
|
|
68
|
+
* `onArchiveChat`; otherwise every chat is listed regardless of this flag.
|
|
69
|
+
*/
|
|
70
|
+
archived?: boolean;
|
|
66
71
|
}
|