@flamingo-stack/openframe-frontend-core 0.0.663 → 0.0.664-2366.7030.1
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/{chunk-HK7R7HSW.cjs → chunk-3SS37SNM.cjs} +10 -10
- package/dist/{chunk-HK7R7HSW.cjs.map → chunk-3SS37SNM.cjs.map} +1 -1
- package/dist/{chunk-BASKR3Z4.cjs → chunk-5R4QMTML.cjs} +8 -4
- package/dist/chunk-5R4QMTML.cjs.map +1 -0
- package/dist/{chunk-B5DZ37OG.cjs → chunk-6FD7ZEBY.cjs} +248 -248
- package/dist/{chunk-B5DZ37OG.cjs.map → chunk-6FD7ZEBY.cjs.map} +1 -1
- package/dist/{chunk-ARMNWO4M.cjs → chunk-6W5N23LC.cjs} +38 -38
- package/dist/{chunk-ARMNWO4M.cjs.map → chunk-6W5N23LC.cjs.map} +1 -1
- package/dist/{chunk-EPV6XTB5.js → chunk-77WMNQTE.js} +3 -3
- package/dist/{chunk-B2LSPZFR.js → chunk-BKCPXDOE.js} +3 -3
- package/dist/{chunk-IXLJIH6U.js → chunk-BPKEDLGR.js} +7 -7
- package/dist/{chunk-OZTH6T4W.js → chunk-CJ5CFXYX.js} +2 -2
- package/dist/{chunk-PW5QV4FH.js → chunk-CQJXOBWK.js} +5 -5
- package/dist/{chunk-WB32HEBY.js → chunk-DNFC6RYF.js} +4 -4
- package/dist/{chunk-ISPIEV7D.cjs → chunk-EMJAT6IK.cjs} +44 -44
- package/dist/{chunk-ISPIEV7D.cjs.map → chunk-EMJAT6IK.cjs.map} +1 -1
- package/dist/{chunk-K56K55H2.cjs → chunk-FGQSSFP4.cjs} +10 -10
- package/dist/{chunk-K56K55H2.cjs.map → chunk-FGQSSFP4.cjs.map} +1 -1
- package/dist/{chunk-WDE7ETA5.cjs → chunk-FJNGXGJW.cjs} +5 -5
- package/dist/{chunk-WDE7ETA5.cjs.map → chunk-FJNGXGJW.cjs.map} +1 -1
- package/dist/{chunk-MRBXYWEX.js → chunk-GDTFJ5QN.js} +2 -2
- package/dist/{chunk-A3L5AJNX.js → chunk-JHAS6Y7P.js} +6 -6
- package/dist/{chunk-4IQC3VKQ.cjs → chunk-JHH7NETU.cjs} +5 -5
- package/dist/{chunk-4IQC3VKQ.cjs.map → chunk-JHH7NETU.cjs.map} +1 -1
- package/dist/{chunk-XCA5HIVS.cjs → chunk-KBUYG5N6.cjs} +33 -33
- package/dist/{chunk-XCA5HIVS.cjs.map → chunk-KBUYG5N6.cjs.map} +1 -1
- package/dist/{chunk-SAM7XUKM.cjs → chunk-L4ZNA3NX.cjs} +3 -3
- package/dist/{chunk-SAM7XUKM.cjs.map → chunk-L4ZNA3NX.cjs.map} +1 -1
- package/dist/{chunk-67DMHSF7.cjs → chunk-LCYYTWRF.cjs} +7 -7
- package/dist/{chunk-67DMHSF7.cjs.map → chunk-LCYYTWRF.cjs.map} +1 -1
- package/dist/{chunk-4AAPEV7A.cjs → chunk-LTW2GWJ2.cjs} +25 -25
- package/dist/{chunk-4AAPEV7A.cjs.map → chunk-LTW2GWJ2.cjs.map} +1 -1
- package/dist/{chunk-UGR37VMX.cjs → chunk-LXL3PZE2.cjs} +12 -12
- package/dist/{chunk-UGR37VMX.cjs.map → chunk-LXL3PZE2.cjs.map} +1 -1
- package/dist/{chunk-TXKAFOSY.js → chunk-MBLACUCE.js} +5 -5
- package/dist/{chunk-BSETJKSW.cjs → chunk-MNUR6PAJ.cjs} +105 -68
- package/dist/chunk-MNUR6PAJ.cjs.map +1 -0
- package/dist/{chunk-JOBTZDZZ.js → chunk-O3GB7JFL.js} +4 -4
- package/dist/{chunk-J75M5PKR.js → chunk-OLCI3UA5.js} +7 -7
- package/dist/{chunk-RP4TSHMY.js → chunk-OMTLCMQB.js} +768 -731
- package/dist/chunk-OMTLCMQB.js.map +1 -0
- package/dist/{chunk-6IU4FW4G.js → chunk-QR3NUFA5.js} +2 -2
- package/dist/{chunk-RZ4UO3OK.js → chunk-RM4S53GB.js} +2 -2
- package/dist/{chunk-SHUKF2HE.js → chunk-RT5JNTCN.js} +4 -4
- package/dist/{chunk-KU7HL52F.js → chunk-VQZXJIPY.js} +8 -4
- package/dist/chunk-VQZXJIPY.js.map +1 -0
- package/dist/{chunk-XWQOOMT2.cjs → chunk-X32X52VN.cjs} +75 -75
- package/dist/{chunk-XWQOOMT2.cjs.map → chunk-X32X52VN.cjs.map} +1 -1
- package/dist/{chunk-KPXGWKFF.cjs → chunk-XCACXPCM.cjs} +22 -22
- package/dist/{chunk-KPXGWKFF.cjs.map → chunk-XCACXPCM.cjs.map} +1 -1
- package/dist/{chunk-2MRQ3XK2.js → chunk-YRMKUDOE.js} +5 -5
- package/dist/{chunk-UZMPTJ5B.js → chunk-Z2MJPTIB.js} +3 -3
- package/dist/{chunk-KYOOTRYM.cjs → chunk-ZGPST26T.cjs} +51 -51
- package/dist/{chunk-KYOOTRYM.cjs.map → chunk-ZGPST26T.cjs.map} +1 -1
- package/dist/{chunk-RDYUPNDO.cjs → chunk-ZMZUF6FX.cjs} +3 -3
- package/dist/{chunk-RDYUPNDO.cjs.map → chunk-ZMZUF6FX.cjs.map} +1 -1
- package/dist/components/case-studies/index.cjs +20 -20
- package/dist/components/case-studies/index.js +5 -5
- package/dist/components/chat/chat-dialog-menu-items.d.ts +15 -0
- package/dist/components/chat/chat-dialog-menu-items.d.ts.map +1 -0
- package/dist/components/chat/chat-panel-header-mobile.d.ts +1 -1
- package/dist/components/chat/chat-panel-header-mobile.d.ts.map +1 -1
- package/dist/components/chat/chat-panel-header.d.ts +6 -4
- package/dist/components/chat/chat-panel-header.d.ts.map +1 -1
- package/dist/components/chat/embeddable-chat.d.ts +2 -1
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +3 -3
- package/dist/components/chat/index.js +2 -2
- package/dist/components/chat/mingo-chat-history.d.ts +6 -4
- package/dist/components/chat/mingo-chat-history.d.ts.map +1 -1
- package/dist/components/chat/mingo-history-rail.d.ts +6 -4
- package/dist/components/chat/mingo-history-rail.d.ts.map +1 -1
- package/dist/components/chat/types/unified-chat-state.types.d.ts +9 -3
- package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +6 -6
- package/dist/components/contact/index.js +5 -5
- package/dist/components/docs/index.cjs +9 -9
- package/dist/components/docs/index.js +8 -8
- package/dist/components/embeds/index.cjs +6 -6
- package/dist/components/embeds/index.js +5 -5
- package/dist/components/faq/index.cjs +6 -6
- package/dist/components/faq/index.js +5 -5
- package/dist/components/features/index.cjs +5 -5
- package/dist/components/features/index.js +4 -4
- package/dist/components/help-center-pages/index.cjs +25 -25
- package/dist/components/help-center-pages/index.js +16 -16
- package/dist/components/icons/empty-vendor-icon.d.ts.map +1 -1
- package/dist/components/icons/index.cjs +2 -2
- package/dist/components/icons/index.js +1 -1
- package/dist/components/index.cjs +42 -42
- package/dist/components/index.js +15 -15
- package/dist/components/meeting-scheduler/index.cjs +28 -28
- package/dist/components/meeting-scheduler/index.js +4 -4
- package/dist/components/navigation/index.cjs +8 -8
- package/dist/components/navigation/index.js +7 -7
- package/dist/components/onboarding-guides/index.cjs +8 -8
- package/dist/components/onboarding-guides/index.js +7 -7
- package/dist/components/tickets/index.cjs +9 -9
- package/dist/components/tickets/index.js +8 -8
- package/dist/components/ui/index.cjs +5 -5
- package/dist/components/ui/index.js +4 -4
- package/dist/hooks/index.cjs +3 -3
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +9 -9
- package/dist/index.js +8 -8
- package/package.json +1 -1
- package/src/components/chat/__tests__/chat-dialog-menu-items.test.tsx +39 -0
- package/src/components/chat/chat-dialog-menu-items.tsx +51 -0
- package/src/components/chat/chat-panel-header-mobile.tsx +7 -7
- package/src/components/chat/chat-panel-header.tsx +11 -10
- package/src/components/chat/embeddable-chat.tsx +17 -7
- package/src/components/chat/mingo-chat-history.tsx +18 -22
- package/src/components/chat/mingo-history-rail.tsx +7 -3
- package/src/components/chat/types/unified-chat-state.types.ts +9 -3
- package/src/components/icons/empty-vendor-icon.tsx +10 -4
- package/dist/chunk-BASKR3Z4.cjs.map +0 -1
- package/dist/chunk-BSETJKSW.cjs.map +0 -1
- package/dist/chunk-KU7HL52F.js.map +0 -1
- package/dist/chunk-RP4TSHMY.js.map +0 -1
- /package/dist/{chunk-EPV6XTB5.js.map → chunk-77WMNQTE.js.map} +0 -0
- /package/dist/{chunk-B2LSPZFR.js.map → chunk-BKCPXDOE.js.map} +0 -0
- /package/dist/{chunk-IXLJIH6U.js.map → chunk-BPKEDLGR.js.map} +0 -0
- /package/dist/{chunk-OZTH6T4W.js.map → chunk-CJ5CFXYX.js.map} +0 -0
- /package/dist/{chunk-PW5QV4FH.js.map → chunk-CQJXOBWK.js.map} +0 -0
- /package/dist/{chunk-WB32HEBY.js.map → chunk-DNFC6RYF.js.map} +0 -0
- /package/dist/{chunk-MRBXYWEX.js.map → chunk-GDTFJ5QN.js.map} +0 -0
- /package/dist/{chunk-A3L5AJNX.js.map → chunk-JHAS6Y7P.js.map} +0 -0
- /package/dist/{chunk-TXKAFOSY.js.map → chunk-MBLACUCE.js.map} +0 -0
- /package/dist/{chunk-JOBTZDZZ.js.map → chunk-O3GB7JFL.js.map} +0 -0
- /package/dist/{chunk-J75M5PKR.js.map → chunk-OLCI3UA5.js.map} +0 -0
- /package/dist/{chunk-6IU4FW4G.js.map → chunk-QR3NUFA5.js.map} +0 -0
- /package/dist/{chunk-RZ4UO3OK.js.map → chunk-RM4S53GB.js.map} +0 -0
- /package/dist/{chunk-SHUKF2HE.js.map → chunk-RT5JNTCN.js.map} +0 -0
- /package/dist/{chunk-2MRQ3XK2.js.map → chunk-YRMKUDOE.js.map} +0 -0
- /package/dist/{chunk-UZMPTJ5B.js.map → chunk-Z2MJPTIB.js.map} +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chatDialogMenuItems` — the one ⋯ menu shared by every conversation surface.
|
|
3
|
+
*
|
|
4
|
+
* Pins the design order (link, rename, compact, archive) and that an action
|
|
5
|
+
* appears only when its handler is wired, so no surface advertises something
|
|
6
|
+
* the host has not implemented.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
10
|
+
|
|
11
|
+
import { chatDialogMenuItems } from '../chat-dialog-menu-items';
|
|
12
|
+
|
|
13
|
+
describe('chatDialogMenuItems', () => {
|
|
14
|
+
it('lists every wired action in design order, each with an icon', () => {
|
|
15
|
+
const items = chatDialogMenuItems({
|
|
16
|
+
onArchive: vi.fn(),
|
|
17
|
+
onCompact: vi.fn(),
|
|
18
|
+
onRename: vi.fn(),
|
|
19
|
+
onCopyLink: vi.fn(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
expect(items.map(item => item.label)).toEqual([
|
|
23
|
+
'Copy Chat Link',
|
|
24
|
+
'Rename Chat',
|
|
25
|
+
'Compact Chat Memory',
|
|
26
|
+
'Archive Chat',
|
|
27
|
+
]);
|
|
28
|
+
expect(items.every(item => item.icon !== undefined)).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('omits actions without a handler', () => {
|
|
32
|
+
const onCompact = vi.fn();
|
|
33
|
+
const items = chatDialogMenuItems({ onCompact });
|
|
34
|
+
|
|
35
|
+
expect(items.map(item => item.id)).toEqual(['compact']);
|
|
36
|
+
items[0].onClick?.();
|
|
37
|
+
expect(onCompact).toHaveBeenCalledOnce();
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { BoxArchiveIcon, Link01HorizontalIcon, PackageCheckIcon, PenEditIcon } from '../icons-v2-generated';
|
|
2
|
+
import type { ActionsMenuItem } from '../ui/actions-menu';
|
|
3
|
+
|
|
4
|
+
export interface ChatDialogMenuActions {
|
|
5
|
+
onCopyLink?: () => void;
|
|
6
|
+
onRename?: () => void;
|
|
7
|
+
onCompact?: () => void;
|
|
8
|
+
onArchive?: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const chatMenuIconClassName = 'h-full w-full text-ods-text-secondary';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The per-conversation ⋯ menu — one list for the desktop header, the mobile
|
|
15
|
+
* header, the split header and every history row, so the four can't drift in
|
|
16
|
+
* order, wording or icons. Each action appears only when its handler is set.
|
|
17
|
+
*/
|
|
18
|
+
export function chatDialogMenuItems({
|
|
19
|
+
onCopyLink,
|
|
20
|
+
onRename,
|
|
21
|
+
onCompact,
|
|
22
|
+
onArchive,
|
|
23
|
+
}: ChatDialogMenuActions): ActionsMenuItem[] {
|
|
24
|
+
const items: (ActionsMenuItem | undefined)[] = [
|
|
25
|
+
onCopyLink && {
|
|
26
|
+
id: 'copy-link',
|
|
27
|
+
label: 'Copy Chat Link',
|
|
28
|
+
icon: <Link01HorizontalIcon className={chatMenuIconClassName} />,
|
|
29
|
+
onClick: onCopyLink,
|
|
30
|
+
},
|
|
31
|
+
onRename && {
|
|
32
|
+
id: 'rename',
|
|
33
|
+
label: 'Rename Chat',
|
|
34
|
+
icon: <PenEditIcon className={chatMenuIconClassName} />,
|
|
35
|
+
onClick: onRename,
|
|
36
|
+
},
|
|
37
|
+
onCompact && {
|
|
38
|
+
id: 'compact',
|
|
39
|
+
label: 'Compact Chat Memory',
|
|
40
|
+
icon: <PackageCheckIcon className={chatMenuIconClassName} />,
|
|
41
|
+
onClick: onCompact,
|
|
42
|
+
},
|
|
43
|
+
onArchive && {
|
|
44
|
+
id: 'archive',
|
|
45
|
+
label: 'Archive Chat',
|
|
46
|
+
icon: <BoxArchiveIcon className={chatMenuIconClassName} />,
|
|
47
|
+
onClick: onArchive,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
return items.filter((item): item is ActionsMenuItem => !!item);
|
|
51
|
+
}
|
|
@@ -4,6 +4,7 @@ import { cn } from '../../utils/cn';
|
|
|
4
4
|
import { Chevron02LeftIcon, ClockHistoryIcon, XmarkIcon } from '../icons-v2-generated';
|
|
5
5
|
import { ActionsMenuDropdown, type ActionsMenuItem } from '../ui/actions-menu';
|
|
6
6
|
import { Button } from '../ui/button';
|
|
7
|
+
import { chatDialogMenuItems, chatMenuIconClassName } from './chat-dialog-menu-items';
|
|
7
8
|
import type { ChatPanelHeaderProps } from './chat-panel-header';
|
|
8
9
|
|
|
9
10
|
export interface ChatPanelHeaderMobileProps extends ChatPanelHeaderProps {
|
|
@@ -38,6 +39,7 @@ export function ChatPanelHeaderMobile({
|
|
|
38
39
|
onRestore,
|
|
39
40
|
onRename,
|
|
40
41
|
onArchive,
|
|
42
|
+
onCompact,
|
|
41
43
|
onCopyLink,
|
|
42
44
|
onOpenArchive,
|
|
43
45
|
className,
|
|
@@ -49,15 +51,13 @@ export function ChatPanelHeaderMobile({
|
|
|
49
51
|
!showBack &&
|
|
50
52
|
onOpenArchive && {
|
|
51
53
|
id: 'open-archive',
|
|
52
|
-
label: 'Chat
|
|
53
|
-
icon: <ClockHistoryIcon className=
|
|
54
|
+
label: 'Chat Archive',
|
|
55
|
+
icon: <ClockHistoryIcon className={chatMenuIconClassName} />,
|
|
54
56
|
onClick: onOpenArchive,
|
|
55
57
|
},
|
|
56
|
-
isArchivedView && onRestore && { id: 'unarchive', label: 'Unarchive
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
!isArchivedView && onArchive && { id: 'archive', label: 'Archive chat', onClick: onArchive },
|
|
60
|
-
].filter(Boolean) as ActionsMenuItem[];
|
|
58
|
+
isArchivedView && onRestore && { id: 'unarchive', label: 'Unarchive Chat', onClick: onRestore },
|
|
59
|
+
...(isArchivedView ? [] : chatDialogMenuItems({ onCopyLink, onRename, onCompact, onArchive })),
|
|
60
|
+
].filter((item): item is ActionsMenuItem => !!item);
|
|
61
61
|
|
|
62
62
|
return (
|
|
63
63
|
<div
|
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
SearchIcon,
|
|
11
11
|
} from '../icons-v2-generated';
|
|
12
12
|
import { XmarkIcon } from '../icons-v2-generated/signs-and-symbols/xmark-icon';
|
|
13
|
-
import { ActionsMenuDropdown
|
|
13
|
+
import { ActionsMenuDropdown } from '../ui/actions-menu';
|
|
14
14
|
import { SquareAvatar } from '../ui/square-avatar';
|
|
15
|
+
import { chatDialogMenuItems } from './chat-dialog-menu-items';
|
|
15
16
|
import { ChatHeaderIconButton } from './chat-header-icon-button';
|
|
16
17
|
import { ChatHeaderSearchField } from './chat-header-search-field';
|
|
17
18
|
import { ChatPanelHeaderMobile } from './chat-panel-header-mobile';
|
|
@@ -41,11 +42,13 @@ export interface ChatPanelHeaderProps {
|
|
|
41
42
|
onClose: () => void;
|
|
42
43
|
/** Restore/unarchive — renders the refresh button (archived view only). */
|
|
43
44
|
onRestore?: () => void;
|
|
44
|
-
/** Rename — adds the "Rename
|
|
45
|
+
/** Rename — adds the "Rename Chat" item to the ⋯ menu. */
|
|
45
46
|
onRename?: () => void;
|
|
46
|
-
/** Archive — adds the "Archive
|
|
47
|
+
/** Archive — adds the "Archive Chat" item to the ⋯ menu. */
|
|
47
48
|
onArchive?: () => void;
|
|
48
|
-
/**
|
|
49
|
+
/** Compact — adds the "Compact Chat Memory" item to the ⋯ menu. */
|
|
50
|
+
onCompact?: () => void;
|
|
51
|
+
/** Copy a shareable link to the open conversation — adds the "Copy Chat Link"
|
|
49
52
|
* item to the ⋯ menu. The host owns the URL and the copy. */
|
|
50
53
|
onCopyLink?: () => void;
|
|
51
54
|
/** Open the Chat Archive page — renders the clock button (list view only). */
|
|
@@ -87,6 +90,7 @@ export function ChatPanelHeader({
|
|
|
87
90
|
onRestore,
|
|
88
91
|
onRename,
|
|
89
92
|
onArchive,
|
|
93
|
+
onCompact,
|
|
90
94
|
onCopyLink,
|
|
91
95
|
onOpenArchive,
|
|
92
96
|
compact = false,
|
|
@@ -97,12 +101,8 @@ export function ChatPanelHeader({
|
|
|
97
101
|
}: ChatPanelHeaderProps) {
|
|
98
102
|
// Search open (with a wired handler) swaps the title for the inline field.
|
|
99
103
|
const searchInline = searchActive && !!onSearchChange;
|
|
100
|
-
// Desktop ⋯ menu (active, non-archived conversation only)
|
|
101
|
-
const menuItems =
|
|
102
|
-
onCopyLink && { id: 'copy-link', label: 'Copy chat link', onClick: onCopyLink },
|
|
103
|
-
onRename && { id: 'rename', label: 'Rename chat', onClick: onRename },
|
|
104
|
-
onArchive && { id: 'archive', label: 'Archive chat', onClick: onArchive },
|
|
105
|
-
].filter(Boolean) as ActionsMenuItem[];
|
|
104
|
+
// Desktop ⋯ menu (active, non-archived conversation only).
|
|
105
|
+
const menuItems = chatDialogMenuItems({ onCopyLink, onRename, onCompact, onArchive });
|
|
106
106
|
|
|
107
107
|
return (
|
|
108
108
|
<>
|
|
@@ -122,6 +122,7 @@ export function ChatPanelHeader({
|
|
|
122
122
|
onRestore={onRestore}
|
|
123
123
|
onRename={onRename}
|
|
124
124
|
onArchive={onArchive}
|
|
125
|
+
onCompact={onCompact}
|
|
125
126
|
onCopyLink={onCopyLink}
|
|
126
127
|
onOpenArchive={onOpenArchive}
|
|
127
128
|
/>
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
} from '../icons-v2-generated';
|
|
55
55
|
import { Chevron02LeftIcon } from '../icons-v2-generated/arrows/chevron-02-left-icon';
|
|
56
56
|
import { XmarkIcon } from '../icons-v2-generated/signs-and-symbols/xmark-icon';
|
|
57
|
-
import { ActionsMenuDropdown
|
|
57
|
+
import { ActionsMenuDropdown } from '../ui/actions-menu';
|
|
58
58
|
import { Button } from '../ui/button';
|
|
59
59
|
import { Drawer, DrawerContent } from '../ui/drawer';
|
|
60
60
|
import { HoverDropdown, type HoverDropdownItem } from '../ui/hover-dropdown';
|
|
@@ -63,6 +63,7 @@ import { SquareAvatar } from '../ui/square-avatar';
|
|
|
63
63
|
import { ChatArchivePage } from './chat-archive-page';
|
|
64
64
|
import { ChatAttachmentChipStrip } from './chat-attachment-bar';
|
|
65
65
|
import { ChatComposer } from './chat-composer';
|
|
66
|
+
import { chatDialogMenuItems } from './chat-dialog-menu-items';
|
|
66
67
|
import { ChatHeaderIconButton } from './chat-header-icon-button';
|
|
67
68
|
import { ChatHeaderSearchField } from './chat-header-search-field';
|
|
68
69
|
import { ChatMessageList } from './chat-message-list';
|
|
@@ -248,8 +249,9 @@ export interface EmbeddableChatProps {
|
|
|
248
249
|
*
|
|
249
250
|
* Same shape an adapter reports through `UnifiedChatState.dialogCapabilities`
|
|
250
251
|
* (`ChatDialogCapabilities`) — one type, whether the list is host-owned or
|
|
251
|
-
* adapter-owned. `onCopyLink` adds "Copy
|
|
252
|
+
* adapter-owned. `onCopyLink` adds "Copy Chat Link" to the header ⋯ menu and
|
|
252
253
|
* every row menu; the host owns the URL shape and the clipboard write.
|
|
254
|
+
* `compactDialog` adds "Compact Chat Memory" to the same menus.
|
|
253
255
|
*/
|
|
254
256
|
mingoDialogCapabilities?: ChatDialogCapabilities;
|
|
255
257
|
|
|
@@ -2023,6 +2025,10 @@ function EmbeddableChatInner({
|
|
|
2023
2025
|
activeDialogId && activeDialog && mingoCaps.canArchive ? () => setArchiveTarget(activeDialog) : undefined;
|
|
2024
2026
|
const headerOnCopyLink =
|
|
2025
2027
|
activeDialogId && activeDialog && mingoCaps.onCopyLink ? () => mingoCaps.onCopyLink?.(activeDialog) : undefined;
|
|
2028
|
+
const headerOnCompact =
|
|
2029
|
+
activeDialogId && activeDialog && mingoCaps.compactDialog
|
|
2030
|
+
? () => mingoCaps.compactDialog?.(activeDialog)
|
|
2031
|
+
: undefined;
|
|
2026
2032
|
const headerOnOpenArchive = fetchArchivedDialogs ? openArchive : undefined;
|
|
2027
2033
|
|
|
2028
2034
|
// Header person (sub-line + 32px avatar, Figma 113:63273): the dialog OWNER
|
|
@@ -2110,11 +2116,12 @@ function EmbeddableChatInner({
|
|
|
2110
2116
|
);
|
|
2111
2117
|
|
|
2112
2118
|
// Desktop split header ⋯ menu (active, non-archived conversation only).
|
|
2113
|
-
const splitHeaderMenuItems =
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2119
|
+
const splitHeaderMenuItems = chatDialogMenuItems({
|
|
2120
|
+
onCopyLink: headerOnCopyLink,
|
|
2121
|
+
onRename: headerOnRename,
|
|
2122
|
+
onCompact: headerOnCompact,
|
|
2123
|
+
onArchive: headerOnArchive,
|
|
2124
|
+
});
|
|
2118
2125
|
|
|
2119
2126
|
// Narrow (single-column) header. The Mingo empty state splits into a "Current
|
|
2120
2127
|
// Chats" list header (search + archive, no back) and a "New Chat" compose
|
|
@@ -2158,6 +2165,7 @@ function EmbeddableChatInner({
|
|
|
2158
2165
|
onRestore: headerOnRestore,
|
|
2159
2166
|
onRename: headerOnRename,
|
|
2160
2167
|
onArchive: headerOnArchive,
|
|
2168
|
+
onCompact: headerOnCompact,
|
|
2161
2169
|
onCopyLink: headerOnCopyLink,
|
|
2162
2170
|
onOpenArchive: headerOnOpenArchive,
|
|
2163
2171
|
};
|
|
@@ -2389,6 +2397,7 @@ function EmbeddableChatInner({
|
|
|
2389
2397
|
onRequestRename={mingoCaps.canRename ? setRenameTarget : undefined}
|
|
2390
2398
|
onRequestArchive={mingoCaps.canArchive ? setArchiveTarget : undefined}
|
|
2391
2399
|
onRequestCopyLink={mingoCaps.onCopyLink}
|
|
2400
|
+
onRequestCompact={mingoCaps.compactDialog}
|
|
2392
2401
|
scope={dialogScope}
|
|
2393
2402
|
onScopeChange={setDialogScope}
|
|
2394
2403
|
searchQuery={mingoCaps.searchQuery}
|
|
@@ -2418,6 +2427,7 @@ function EmbeddableChatInner({
|
|
|
2418
2427
|
onRequestRename={mingoCaps.canRename ? setRenameTarget : undefined}
|
|
2419
2428
|
onRequestArchive={mingoCaps.canArchive ? setArchiveTarget : undefined}
|
|
2420
2429
|
onRequestCopyLink={mingoCaps.onCopyLink}
|
|
2430
|
+
onRequestCompact={mingoCaps.compactDialog}
|
|
2421
2431
|
scope={dialogScope}
|
|
2422
2432
|
onScopeChange={setDialogScope}
|
|
2423
2433
|
searchQuery={mingoCaps.searchQuery}
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
4
4
|
import { cn } from '../../utils/cn';
|
|
5
5
|
import { Ellipsis01Icon, SearchXmarkIcon } from '../icons-v2-generated';
|
|
6
|
-
import { ActionsMenuDropdown
|
|
6
|
+
import { ActionsMenuDropdown } from '../ui/actions-menu';
|
|
7
7
|
import { Button } from '../ui/button';
|
|
8
8
|
import { ScrollFadeOverlay, useScrollFade } from '../ui/scroll-fade';
|
|
9
9
|
import { SquareAvatar } from '../ui/square-avatar';
|
|
10
|
+
import { chatDialogMenuItems } from './chat-dialog-menu-items';
|
|
10
11
|
import { ChatListEmptyState } from './chat-list-empty-state';
|
|
11
12
|
import type { DialogItem } from './types/component.types';
|
|
12
13
|
|
|
@@ -21,16 +22,18 @@ export interface MingoChatHistoryProps {
|
|
|
21
22
|
activeDialogId?: string;
|
|
22
23
|
/** Open a dialog. */
|
|
23
24
|
onSelectDialog?: (id: string) => void;
|
|
24
|
-
/** Request rename — enables the row "Rename
|
|
25
|
+
/** Request rename — enables the row "Rename Chat" action. The host opens
|
|
25
26
|
* the Rename modal; the list does no inline editing. */
|
|
26
27
|
onRequestRename?: (dialog: DialogItem) => void;
|
|
27
|
-
/** Request archive — enables the row "Archive
|
|
28
|
+
/** Request archive — enables the row "Archive Chat" action. The host opens
|
|
28
29
|
* the Archive confirmation modal. */
|
|
29
30
|
onRequestArchive?: (dialog: DialogItem) => void;
|
|
30
|
-
/** Request a shareable link — enables the row "Copy
|
|
31
|
+
/** Request a shareable link — enables the row "Copy Chat Link" action. The host
|
|
31
32
|
* owns the URL shape and the copy itself (the list knows neither the app's
|
|
32
33
|
* routes nor whether a clipboard is available). */
|
|
33
34
|
onRequestCopyLink?: (dialog: DialogItem) => void;
|
|
35
|
+
/** Request context compaction — enables the row "Compact Chat Memory" action. */
|
|
36
|
+
onRequestCompact?: (dialog: DialogItem) => void;
|
|
34
37
|
/** Current server-side search term. Drives the "No chats found" empty state;
|
|
35
38
|
* the search INPUT lives in the panel header, not in this list. The host
|
|
36
39
|
* owns the term and refetches server-side — the list does no filtering. */
|
|
@@ -93,6 +96,7 @@ interface RowProps {
|
|
|
93
96
|
onSelect?: (id: string) => void;
|
|
94
97
|
onRequestRename?: (dialog: DialogItem) => void;
|
|
95
98
|
onRequestCopyLink?: (dialog: DialogItem) => void;
|
|
99
|
+
onRequestCompact?: (dialog: DialogItem) => void;
|
|
96
100
|
onRequestArchive?: (dialog: DialogItem) => void;
|
|
97
101
|
}
|
|
98
102
|
|
|
@@ -102,34 +106,24 @@ function MingoChatHistoryRow({
|
|
|
102
106
|
onSelect,
|
|
103
107
|
onRequestCopyLink,
|
|
104
108
|
onRequestRename,
|
|
109
|
+
onRequestCompact,
|
|
105
110
|
onRequestArchive,
|
|
106
111
|
}: RowProps) {
|
|
107
112
|
const title = dialog.title || 'Untitled Chat';
|
|
108
113
|
const unread = dialog.unreadMessagesCount ?? 0;
|
|
109
|
-
const hasMenu = !!onRequestRename || !!onRequestArchive || !!onRequestCopyLink;
|
|
114
|
+
const hasMenu = !!onRequestRename || !!onRequestArchive || !!onRequestCopyLink || !!onRequestCompact;
|
|
110
115
|
const owner = dialog.owner;
|
|
111
116
|
const hasAvatar = !!(owner?.name || owner?.avatarUrl);
|
|
112
117
|
// Keep the `⋯` visible while its menu is open — once Radix moves focus into
|
|
113
118
|
// the portalled content the row loses hover/focus-within.
|
|
114
119
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
115
120
|
|
|
116
|
-
const menuItems =
|
|
117
|
-
onRequestCopyLink &&
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
onRequestRename && {
|
|
123
|
-
id: 'rename',
|
|
124
|
-
label: 'Rename chat',
|
|
125
|
-
onClick: () => onRequestRename(dialog),
|
|
126
|
-
},
|
|
127
|
-
onRequestArchive && {
|
|
128
|
-
id: 'archive',
|
|
129
|
-
label: 'Archive chat',
|
|
130
|
-
onClick: () => onRequestArchive(dialog),
|
|
131
|
-
},
|
|
132
|
-
].filter(Boolean) as ActionsMenuItem[];
|
|
121
|
+
const menuItems = chatDialogMenuItems({
|
|
122
|
+
onCopyLink: onRequestCopyLink && (() => onRequestCopyLink(dialog)),
|
|
123
|
+
onRename: onRequestRename && (() => onRequestRename(dialog)),
|
|
124
|
+
onCompact: onRequestCompact && (() => onRequestCompact(dialog)),
|
|
125
|
+
onArchive: onRequestArchive && (() => onRequestArchive(dialog)),
|
|
126
|
+
});
|
|
133
127
|
|
|
134
128
|
// The item is the full-width row (inside the group's bordered box). Padding
|
|
135
129
|
// lives on the inner content button (badge + title) only — the `⋯` is a
|
|
@@ -317,6 +311,7 @@ export function MingoChatHistory({
|
|
|
317
311
|
onSelectDialog,
|
|
318
312
|
onRequestCopyLink,
|
|
319
313
|
onRequestRename,
|
|
314
|
+
onRequestCompact,
|
|
320
315
|
onRequestArchive,
|
|
321
316
|
searchQuery,
|
|
322
317
|
hasMore = false,
|
|
@@ -400,6 +395,7 @@ export function MingoChatHistory({
|
|
|
400
395
|
onSelect={onSelectDialog}
|
|
401
396
|
onRequestCopyLink={onRequestCopyLink}
|
|
402
397
|
onRequestRename={onRequestRename}
|
|
398
|
+
onRequestCompact={onRequestCompact}
|
|
403
399
|
onRequestArchive={onRequestArchive}
|
|
404
400
|
/>
|
|
405
401
|
))}
|
|
@@ -29,12 +29,14 @@ export interface MingoHistoryRailProps {
|
|
|
29
29
|
* the welcome. Rendered as the pinned "Start New Chat" button above the list,
|
|
30
30
|
* in every state (including the no-chats empty state). */
|
|
31
31
|
onNewChat?: () => void;
|
|
32
|
-
/** Request rename — enables the row "Rename
|
|
32
|
+
/** Request rename — enables the row "Rename Chat" action. */
|
|
33
33
|
onRequestRename?: (dialog: DialogItem) => void;
|
|
34
|
-
/** Request archive — enables the row "Archive
|
|
34
|
+
/** Request archive — enables the row "Archive Chat" action. */
|
|
35
35
|
onRequestArchive?: (dialog: DialogItem) => void;
|
|
36
|
-
/** Request a shareable link — enables the row "Copy
|
|
36
|
+
/** Request a shareable link — enables the row "Copy Chat Link" action. */
|
|
37
37
|
onRequestCopyLink?: (dialog: DialogItem) => void;
|
|
38
|
+
/** Request context compaction — enables the row "Compact Chat Memory" action. */
|
|
39
|
+
onRequestCompact?: (dialog: DialogItem) => void;
|
|
38
40
|
/** Ownership scope shown as a two-state "My Chats / All Chats" selector
|
|
39
41
|
* between "Start New Chat" and the list. Rendered only when BOTH `scope`
|
|
40
42
|
* and `onScopeChange` are provided; the host owns the state and refilters
|
|
@@ -88,6 +90,7 @@ export function MingoHistoryRail({
|
|
|
88
90
|
onRequestRename,
|
|
89
91
|
onRequestArchive,
|
|
90
92
|
onRequestCopyLink,
|
|
93
|
+
onRequestCompact,
|
|
91
94
|
scope,
|
|
92
95
|
onScopeChange,
|
|
93
96
|
searchQuery,
|
|
@@ -169,6 +172,7 @@ export function MingoHistoryRail({
|
|
|
169
172
|
onRequestRename={onRequestRename}
|
|
170
173
|
onRequestArchive={onRequestArchive}
|
|
171
174
|
onRequestCopyLink={onRequestCopyLink}
|
|
175
|
+
onRequestCompact={onRequestCompact}
|
|
172
176
|
searchQuery={searchQuery}
|
|
173
177
|
hasMore={hasMore}
|
|
174
178
|
isLoadingMore={isLoadingMore}
|
|
@@ -49,9 +49,9 @@ export interface FetchDialogsResult {
|
|
|
49
49
|
* or adapter-owned (`UnifiedChatState.dialogCapabilities`).
|
|
50
50
|
*/
|
|
51
51
|
export interface ChatDialogCapabilities {
|
|
52
|
-
/** Show "Rename
|
|
52
|
+
/** Show "Rename Chat" in the row ⋯ menu and the conversation header. */
|
|
53
53
|
canRename?: boolean;
|
|
54
|
-
/** Show "Archive
|
|
54
|
+
/** Show "Archive Chat" in the row ⋯ menu and the conversation header. */
|
|
55
55
|
canArchive?: boolean;
|
|
56
56
|
/** Pages archived dialogs — presence gates the archive page + header button. */
|
|
57
57
|
fetchArchivedDialogs?: (params: FetchDialogsParams) => Promise<FetchDialogsResult>;
|
|
@@ -61,8 +61,14 @@ export interface ChatDialogCapabilities {
|
|
|
61
61
|
searchQuery?: string;
|
|
62
62
|
/** Presence wires the header magnifier + the rail's search field. */
|
|
63
63
|
onSearchChange?: (query: string) => void;
|
|
64
|
-
/** "Copy
|
|
64
|
+
/** "Copy Chat Link" — the owner of the URL shape + clipboard write. */
|
|
65
65
|
onCopyLink?: (dialog: DialogItem) => void;
|
|
66
|
+
/**
|
|
67
|
+
* "Compact Chat Memory" — summarizes the dialog's AI context on demand. The
|
|
68
|
+
* host owns the request and its feedback; the compaction itself streams into
|
|
69
|
+
* the thread as the usual context-compaction message.
|
|
70
|
+
*/
|
|
71
|
+
compactDialog?: (dialog: DialogItem) => void;
|
|
66
72
|
/**
|
|
67
73
|
* When the list has settled EMPTY and is unsearched, land on the composer
|
|
68
74
|
* instead of an empty "Current Chats" screen.
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import { useId } from 'react';
|
|
2
|
+
|
|
1
3
|
interface EmptyVendorIconProps {
|
|
2
4
|
className?: string;
|
|
3
5
|
}
|
|
4
6
|
|
|
5
7
|
/** @deprecated Use icons from icons-v2-generated instead. */
|
|
6
8
|
export function EmptyVendorIcon({ className }: EmptyVendorIconProps) {
|
|
9
|
+
const uniqueId = useId();
|
|
10
|
+
const patternId = `pattern0_1643_33816_${uniqueId}`;
|
|
11
|
+
const imageId = `image0_1643_33816_${uniqueId}`;
|
|
12
|
+
|
|
7
13
|
return (
|
|
8
14
|
<svg
|
|
9
15
|
width="24"
|
|
@@ -16,14 +22,14 @@ export function EmptyVendorIcon({ className }: EmptyVendorIconProps) {
|
|
|
16
22
|
>
|
|
17
23
|
<path
|
|
18
24
|
d="M0 4C0 1.79086 1.79086 0 4 0H20C22.2091 0 24 1.79086 24 4V20C24 22.2091 22.2091 24 20 24H4C1.79086 24 0 22.2091 0 20V4Z"
|
|
19
|
-
fill=
|
|
25
|
+
fill={`url(#${patternId})`}
|
|
20
26
|
/>
|
|
21
27
|
<defs>
|
|
22
|
-
<pattern id=
|
|
23
|
-
<use xlinkHref=
|
|
28
|
+
<pattern id={patternId} patternContentUnits="objectBoundingBox" width="1" height="1">
|
|
29
|
+
<use xlinkHref={`#${imageId}`} transform="scale(0.0104167)" />
|
|
24
30
|
</pattern>
|
|
25
31
|
<image
|
|
26
|
-
id=
|
|
32
|
+
id={imageId}
|
|
27
33
|
width="96"
|
|
28
34
|
height="96"
|
|
29
35
|
preserveAspectRatio="none"
|