@flamingo-stack/openframe-frontend-core 0.0.219 → 0.0.220-snapshot.20260602171504
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-EDW2NVRV.js → chunk-4WZOFD46.js} +37 -37
- package/dist/{chunk-EDW2NVRV.js.map → chunk-4WZOFD46.js.map} +1 -1
- package/dist/{chunk-ZGBXHK26.cjs → chunk-5GN7TXHY.cjs} +12 -12
- package/dist/{chunk-ZGBXHK26.cjs.map → chunk-5GN7TXHY.cjs.map} +1 -1
- package/dist/{chunk-F3FO2ZZZ.cjs → chunk-BAKZF4GU.cjs} +7 -7
- package/dist/{chunk-F3FO2ZZZ.cjs.map → chunk-BAKZF4GU.cjs.map} +1 -1
- package/dist/{chunk-MPHDM2VZ.cjs → chunk-BCL24DFU.cjs} +30 -30
- package/dist/{chunk-MPHDM2VZ.cjs.map → chunk-BCL24DFU.cjs.map} +1 -1
- package/dist/{chunk-65CPJ4SX.cjs → chunk-C6ASEPZL.cjs} +30 -30
- package/dist/{chunk-65CPJ4SX.cjs.map → chunk-C6ASEPZL.cjs.map} +1 -1
- package/dist/{chunk-SZXKKEUH.cjs → chunk-E6B4B7GM.cjs} +46 -30
- package/dist/chunk-E6B4B7GM.cjs.map +1 -0
- package/dist/{chunk-SRA2QYK6.js → chunk-HUA4XG4S.js} +4 -4
- package/dist/{chunk-A3PL6ZCF.js → chunk-KXF3WCPH.js} +6397 -5128
- package/dist/chunk-KXF3WCPH.js.map +1 -0
- package/dist/{chunk-SL3RGBPX.cjs → chunk-QNYH3WUU.cjs} +9 -9
- package/dist/{chunk-SL3RGBPX.cjs.map → chunk-QNYH3WUU.cjs.map} +1 -1
- package/dist/{chunk-24Q2WLIU.js → chunk-QYRV6MKX.js} +2 -2
- package/dist/{chunk-XG7DFRJL.js → chunk-RCECOGMI.js} +3 -3
- package/dist/{chunk-7UZLRI7W.cjs → chunk-SEECETJY.cjs} +3301 -2032
- package/dist/chunk-SEECETJY.cjs.map +1 -0
- package/dist/{chunk-ZII7TNVA.js → chunk-T5MEXJD5.js} +3 -3
- package/dist/{chunk-YX3YQNC4.cjs → chunk-W23DRJAA.cjs} +13 -13
- package/dist/{chunk-YX3YQNC4.cjs.map → chunk-W23DRJAA.cjs.map} +1 -1
- package/dist/{chunk-DRPECAXO.js → chunk-WR32ZE63.js} +2 -2
- package/dist/{chunk-Y3MXGCOW.js → chunk-YZDUOUMB.js} +46 -30
- package/dist/chunk-YZDUOUMB.js.map +1 -0
- package/dist/components/chat/chat-archive-page.d.ts +25 -0
- package/dist/components/chat/chat-archive-page.d.ts.map +1 -0
- package/dist/components/chat/chat-composer.d.ts +29 -0
- package/dist/components/chat/chat-composer.d.ts.map +1 -0
- package/dist/components/chat/chat-header-icon-button.d.ts +14 -0
- package/dist/components/chat/chat-header-icon-button.d.ts.map +1 -0
- package/dist/components/chat/chat-panel-header.d.ts +32 -0
- package/dist/components/chat/chat-panel-header.d.ts.map +1 -0
- package/dist/components/chat/embeddable-chat.d.ts +18 -0
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/guide-mode-banner.d.ts +16 -0
- package/dist/components/chat/guide-mode-banner.d.ts.map +1 -0
- package/dist/components/chat/guide-welcome.d.ts +40 -0
- package/dist/components/chat/guide-welcome.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat-dialog-manager.d.ts +58 -0
- package/dist/components/chat/hooks/use-chat-dialog-manager.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +26 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-sse-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-unified-chat.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +29 -5
- package/dist/components/chat/index.cjs.map +1 -1
- package/dist/components/chat/index.d.ts +9 -0
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +28 -4
- package/dist/components/chat/mingo-chat-history.d.ts +37 -0
- package/dist/components/chat/mingo-chat-history.d.ts.map +1 -0
- package/dist/components/chat/mingo-chat-modals.d.ts +50 -0
- package/dist/components/chat/mingo-chat-modals.d.ts.map +1 -0
- package/dist/components/chat/mingo-onboarding-card.d.ts.map +1 -1
- package/dist/components/chat/mingo-welcome.d.ts +78 -0
- package/dist/components/chat/mingo-welcome.d.ts.map +1 -0
- package/dist/components/chat/types/unified-chat-state.types.d.ts +6 -0
- 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/features/index.cjs +5 -5
- package/dist/components/features/index.js +4 -4
- package/dist/components/icons-v2-generated/brand-logos/fleet-mdm-logo-grey-icon.d.ts.map +1 -1
- package/dist/components/icons-v2-generated/brand-logos/fleet-mdm-logo-icon.d.ts.map +1 -1
- package/dist/components/icons-v2-generated/index.cjs +2 -2
- package/dist/components/icons-v2-generated/index.js +1 -1
- package/dist/components/index.cjs +128 -104
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +31 -7
- package/dist/components/index.js.map +1 -1
- package/dist/components/layout/page-heading.d.ts +7 -6
- package/dist/components/layout/page-heading.d.ts.map +1 -1
- package/dist/components/navigation/app-layout-drawer.d.ts.map +1 -1
- package/dist/components/navigation/header-mingo-button.d.ts +4 -2
- package/dist/components/navigation/header-mingo-button.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +5 -5
- package/dist/components/navigation/index.js +4 -4
- package/dist/components/onboarding-guides/index.cjs +28 -28
- package/dist/components/onboarding-guides/index.js +6 -6
- package/dist/components/tickets/index.cjs +88 -88
- package/dist/components/tickets/index.js +7 -7
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +50 -50
- package/dist/components/ui/file-manager/index.js +1 -1
- package/dist/components/ui/index.cjs +29 -5
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +28 -4
- package/dist/components/ui/modal-v2.d.ts.map +1 -1
- package/dist/components/ui/more-actions-menu.d.ts +8 -1
- package/dist/components/ui/more-actions-menu.d.ts.map +1 -1
- package/dist/components/ui/portal-container.d.ts +21 -0
- package/dist/components/ui/portal-container.d.ts.map +1 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/hooks/index.cjs +3 -3
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +29 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +28 -4
- package/package.json +1 -1
- package/src/components/chat/chat-archive-page.tsx +93 -0
- package/src/components/chat/chat-composer.tsx +99 -0
- package/src/components/chat/chat-header-icon-button.tsx +36 -0
- package/src/components/chat/chat-panel-header.tsx +114 -0
- package/src/components/chat/embeddable-chat.tsx +386 -311
- package/src/components/chat/guide-mode-banner.tsx +75 -0
- package/src/components/chat/guide-welcome.tsx +207 -0
- package/src/components/chat/hooks/use-chat-dialog-manager.ts +227 -0
- package/src/components/chat/hooks/use-nats-chat-adapter.ts +85 -0
- package/src/components/chat/hooks/use-sse-chat-adapter.ts +8 -0
- package/src/components/chat/hooks/use-unified-chat.ts +12 -0
- package/src/components/chat/index.ts +9 -0
- package/src/components/chat/mingo-chat-history.tsx +308 -0
- package/src/components/chat/mingo-chat-modals.tsx +223 -0
- package/src/components/chat/mingo-onboarding-card.tsx +5 -8
- package/src/components/chat/mingo-welcome.tsx +396 -0
- package/src/components/chat/types/unified-chat-state.types.ts +8 -0
- package/src/components/icons-v2/brand-logos/fleet-mdm-logo-grey.svg +6 -6
- package/src/components/icons-v2/brand-logos/fleet-mdm-logo.svg +6 -6
- package/src/components/icons-v2-generated/brand-logos/fleet-mdm-logo-grey-icon.tsx +2 -22
- package/src/components/icons-v2-generated/brand-logos/fleet-mdm-logo-icon.tsx +22 -2
- package/src/components/layout/page-heading.tsx +13 -7
- package/src/components/navigation/app-header.tsx +12 -12
- package/src/components/navigation/app-layout-drawer.tsx +25 -15
- package/src/components/navigation/header-mingo-button.tsx +22 -7
- package/src/components/ui/dropdown-menu.tsx +9 -3
- package/src/components/ui/modal-v2.tsx +33 -3
- package/src/components/ui/more-actions-menu.tsx +15 -2
- package/src/components/ui/portal-container.tsx +28 -0
- package/src/components/ui/tooltip.tsx +9 -3
- package/src/stories/AppLayoutSidebar.stories.tsx +184 -0
- package/src/stories/EmbeddableChat.stories.tsx +114 -0
- package/src/stories/GuideWelcome.stories.tsx +102 -0
- package/src/stories/MingoChatModals.stories.tsx +82 -0
- package/src/stories/MingoWelcome.stories.tsx +119 -0
- package/dist/chunk-7UZLRI7W.cjs.map +0 -1
- package/dist/chunk-A3PL6ZCF.js.map +0 -1
- package/dist/chunk-SZXKKEUH.cjs.map +0 -1
- package/dist/chunk-Y3MXGCOW.js.map +0 -1
- /package/dist/{chunk-SRA2QYK6.js.map → chunk-HUA4XG4S.js.map} +0 -0
- /package/dist/{chunk-24Q2WLIU.js.map → chunk-QYRV6MKX.js.map} +0 -0
- /package/dist/{chunk-XG7DFRJL.js.map → chunk-RCECOGMI.js.map} +0 -0
- /package/dist/{chunk-ZII7TNVA.js.map → chunk-T5MEXJD5.js.map} +0 -0
- /package/dist/{chunk-DRPECAXO.js.map → chunk-WR32ZE63.js.map} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Chevron02LeftIcon } from '../icons-v2-generated'
|
|
5
|
+
import { XmarkIcon } from '../icons-v2-generated/signs-and-symbols/xmark-icon'
|
|
6
|
+
import { ChatHeaderIconButton } from './chat-header-icon-button'
|
|
7
|
+
import { MingoChatHistory } from './mingo-chat-history'
|
|
8
|
+
import type { DialogItem } from './types/component.types'
|
|
9
|
+
|
|
10
|
+
export interface ChatArchivePageProps {
|
|
11
|
+
/** Archived dialogs, grouped (Today / Yesterday / Older) by the list. */
|
|
12
|
+
dialogs: ReadonlyArray<DialogItem>
|
|
13
|
+
/** Open an archived dialog. */
|
|
14
|
+
onSelectDialog: (id: string) => void
|
|
15
|
+
/** Back chevron — returns to the previous (list) view. */
|
|
16
|
+
onBack: () => void
|
|
17
|
+
/** Close the whole chat panel. */
|
|
18
|
+
onClose: () => void
|
|
19
|
+
/** True while a page is loading (drives the empty/loading copy + spinner). */
|
|
20
|
+
isLoading?: boolean
|
|
21
|
+
/** Whether another page of archived dialogs remains. */
|
|
22
|
+
hasMore?: boolean
|
|
23
|
+
/** Fetch the next page. */
|
|
24
|
+
onLoadMore?: () => void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Chat Archive page — Figma node `7361:427312`. Back + title + close header
|
|
29
|
+
* over the date-grouped archived-dialog list (reuses `MingoChatHistory`
|
|
30
|
+
* without the row action menus).
|
|
31
|
+
*/
|
|
32
|
+
export function ChatArchivePage({
|
|
33
|
+
dialogs,
|
|
34
|
+
onSelectDialog,
|
|
35
|
+
onBack,
|
|
36
|
+
onClose,
|
|
37
|
+
isLoading = false,
|
|
38
|
+
hasMore = false,
|
|
39
|
+
onLoadMore,
|
|
40
|
+
}: ChatArchivePageProps) {
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
<div className="flex-shrink-0 flex h-14 w-full overflow-hidden border-b border-ods-border bg-ods-card">
|
|
44
|
+
<div className="flex flex-1 min-w-0 items-center gap-2 px-4 py-3">
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
onClick={onBack}
|
|
48
|
+
aria-label="Back"
|
|
49
|
+
className="inline-flex shrink-0 items-center justify-center size-8 -ml-1 rounded-md text-ods-text-secondary transition-colors hover:bg-ods-bg-hover hover:text-ods-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-ods-accent"
|
|
50
|
+
>
|
|
51
|
+
<Chevron02LeftIcon size={20} />
|
|
52
|
+
</button>
|
|
53
|
+
<span className="truncate text-h3 text-ods-text-primary">
|
|
54
|
+
Chat Archive
|
|
55
|
+
</span>
|
|
56
|
+
</div>
|
|
57
|
+
<ChatHeaderIconButton onClick={onClose} aria-label="Close">
|
|
58
|
+
<XmarkIcon size={24} />
|
|
59
|
+
</ChatHeaderIconButton>
|
|
60
|
+
</div>
|
|
61
|
+
<div className="flex flex-1 min-h-0 flex-col p-[var(--spacing-system-m)]">
|
|
62
|
+
{dialogs.length > 0 ? (
|
|
63
|
+
<MingoChatHistory
|
|
64
|
+
dialogs={dialogs}
|
|
65
|
+
onSelectDialog={onSelectDialog}
|
|
66
|
+
hasMore={hasMore}
|
|
67
|
+
isLoadingMore={isLoading && dialogs.length > 0}
|
|
68
|
+
onLoadMore={onLoadMore}
|
|
69
|
+
/>
|
|
70
|
+
) : isLoading ? (
|
|
71
|
+
// First-load skeleton — `h-12` rows matching the dialog-list layout
|
|
72
|
+
// so results land without a shift (auth → data → empty → content).
|
|
73
|
+
<div className="flex flex-col" aria-hidden>
|
|
74
|
+
{[...Array(6)].map((_, i) => (
|
|
75
|
+
<div
|
|
76
|
+
key={i}
|
|
77
|
+
className="flex h-12 items-center gap-[var(--spacing-system-xsf)] border-b border-ods-border px-[var(--spacing-system-s)] last:border-b-0"
|
|
78
|
+
>
|
|
79
|
+
<div className="h-4 w-full max-w-[60%] animate-pulse rounded bg-ods-bg-secondary" />
|
|
80
|
+
</div>
|
|
81
|
+
))}
|
|
82
|
+
</div>
|
|
83
|
+
) : (
|
|
84
|
+
<div className="flex flex-1 items-center justify-center text-center">
|
|
85
|
+
<p className="text-h4 text-ods-text-secondary">
|
|
86
|
+
No archived chats yet.
|
|
87
|
+
</p>
|
|
88
|
+
</div>
|
|
89
|
+
)}
|
|
90
|
+
</div>
|
|
91
|
+
</>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { ChatFooter } from './chat-container'
|
|
5
|
+
import { ChatInput } from './chat-input'
|
|
6
|
+
import { ChatAttachmentAddButton } from './chat-attachment-bar'
|
|
7
|
+
import { ModelDisplay } from './model-display'
|
|
8
|
+
import { BoxArchiveIcon } from '../icons-v2-generated'
|
|
9
|
+
import type { ChatInputRef, ModelDisplayProps } from './types/component.types'
|
|
10
|
+
|
|
11
|
+
export interface ChatComposerProps {
|
|
12
|
+
/** Read-only archived chat → render the unarchive placeholder instead of the
|
|
13
|
+
* input (Figma node 7361:426949). */
|
|
14
|
+
archived?: boolean
|
|
15
|
+
inputRef: React.Ref<ChatInputRef>
|
|
16
|
+
onSend: (text: string) => void
|
|
17
|
+
onStop: () => void
|
|
18
|
+
sending: boolean
|
|
19
|
+
placeholder: string
|
|
20
|
+
autoFocus?: boolean
|
|
21
|
+
slashCommands?: React.ComponentProps<typeof ChatInput>['slashCommands']
|
|
22
|
+
/** Show the (Guide-only) attachment add button to the left of the model row. */
|
|
23
|
+
showAttachmentButton?: boolean
|
|
24
|
+
attachmentsCount?: number
|
|
25
|
+
onAddFiles?: (files: FileList | File[]) => void
|
|
26
|
+
attachmentsDisabled?: boolean
|
|
27
|
+
/** Model + usage row props, forwarded to `<ModelDisplay>`. */
|
|
28
|
+
model: ModelDisplayProps
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Chat panel footer (Figma node 7363:205952): the message composer (live
|
|
33
|
+
* `ChatInput` or the read-only archived placeholder) above the model/usage
|
|
34
|
+
* row. No own background — inherits the panel surface so it blends seamlessly.
|
|
35
|
+
*/
|
|
36
|
+
export function ChatComposer({
|
|
37
|
+
archived = false,
|
|
38
|
+
inputRef,
|
|
39
|
+
onSend,
|
|
40
|
+
onStop,
|
|
41
|
+
sending,
|
|
42
|
+
placeholder,
|
|
43
|
+
autoFocus,
|
|
44
|
+
slashCommands,
|
|
45
|
+
showAttachmentButton = false,
|
|
46
|
+
attachmentsCount = 0,
|
|
47
|
+
onAddFiles,
|
|
48
|
+
attachmentsDisabled = false,
|
|
49
|
+
model,
|
|
50
|
+
}: ChatComposerProps) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
className="flex-shrink-0 px-[var(--spacing-system-m)] pb-[var(--spacing-system-m)] flex flex-col gap-[var(--spacing-system-xxs)]"
|
|
54
|
+
style={{ paddingBottom: 'max(1rem, env(safe-area-inset-bottom))' }}
|
|
55
|
+
>
|
|
56
|
+
<ChatFooter className="!p-0" fullWidth>
|
|
57
|
+
{archived ? (
|
|
58
|
+
<div className="flex w-full items-center justify-center gap-[var(--spacing-system-xs)] rounded-md border border-ods-border bg-ods-card p-[var(--spacing-system-sf)]">
|
|
59
|
+
<BoxArchiveIcon size={24} className="shrink-0 text-ods-text-secondary" />
|
|
60
|
+
<p className="truncate text-h4 text-ods-text-secondary">
|
|
61
|
+
Unarchive the chat to continue
|
|
62
|
+
</p>
|
|
63
|
+
</div>
|
|
64
|
+
) : (
|
|
65
|
+
<ChatInput
|
|
66
|
+
ref={inputRef}
|
|
67
|
+
onSend={onSend}
|
|
68
|
+
onStop={onStop}
|
|
69
|
+
sending={sending}
|
|
70
|
+
placeholder={placeholder}
|
|
71
|
+
fullWidth
|
|
72
|
+
className="px-0"
|
|
73
|
+
reserveAvatarOffset={false}
|
|
74
|
+
autoFocus={autoFocus}
|
|
75
|
+
slashCommands={slashCommands}
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
</ChatFooter>
|
|
79
|
+
|
|
80
|
+
<div className="flex items-center gap-2 w-full">
|
|
81
|
+
{showAttachmentButton && onAddFiles && (
|
|
82
|
+
// Attachments are Guide-only: the NATS agent backend doesn't accept
|
|
83
|
+
// them, so the add-button is hidden in Mingo mode. Skipping the
|
|
84
|
+
// render entirely (not just the icon) collapses the otherwise-
|
|
85
|
+
// invisible 28px placeholder slot the component leaves for layout.
|
|
86
|
+
<ChatAttachmentAddButton
|
|
87
|
+
attachmentsEnabled
|
|
88
|
+
attachmentsCount={attachmentsCount}
|
|
89
|
+
onAddFiles={onAddFiles}
|
|
90
|
+
disabled={attachmentsDisabled}
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
<div className="flex-1 min-w-0">
|
|
94
|
+
<ModelDisplay {...model} />
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { cn } from '../../utils/cn'
|
|
5
|
+
|
|
6
|
+
export interface ChatHeaderIconButtonProps
|
|
7
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Square 56×56 icon cell used in the chat panel's top-navigation
|
|
11
|
+
* (archive / restore / close, and the `⋯` menu trigger). A left border acts
|
|
12
|
+
* as the 1px divider between cells.
|
|
13
|
+
*
|
|
14
|
+
* On hover only the background changes (`ods-bg-hover`) — the icon keeps its
|
|
15
|
+
* `ods-text-secondary` colour. `forwardRef` + prop spread so it works as a
|
|
16
|
+
* Radix `asChild` trigger.
|
|
17
|
+
*/
|
|
18
|
+
export const ChatHeaderIconButton = React.forwardRef<
|
|
19
|
+
HTMLButtonElement,
|
|
20
|
+
ChatHeaderIconButtonProps
|
|
21
|
+
>(({ className, children, type = 'button', ...props }, ref) => (
|
|
22
|
+
<button
|
|
23
|
+
ref={ref}
|
|
24
|
+
type={type}
|
|
25
|
+
className={cn(
|
|
26
|
+
'flex size-14 shrink-0 items-center justify-center border-l border-ods-border',
|
|
27
|
+
'text-ods-text-secondary transition-colors hover:bg-ods-bg-hover',
|
|
28
|
+
'focus:outline-none focus-visible:ring-2 focus-visible:ring-ods-accent',
|
|
29
|
+
className,
|
|
30
|
+
)}
|
|
31
|
+
{...props}
|
|
32
|
+
>
|
|
33
|
+
{children}
|
|
34
|
+
</button>
|
|
35
|
+
))
|
|
36
|
+
ChatHeaderIconButton.displayName = 'ChatHeaderIconButton'
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Chevron01LeftIcon } from '../icons-v2-generated/arrows/chevron-01-left-icon'
|
|
5
|
+
import {
|
|
6
|
+
Ellipsis01Icon,
|
|
7
|
+
ClockHistoryIcon,
|
|
8
|
+
Refresh01LeftIcon,
|
|
9
|
+
} from '../icons-v2-generated'
|
|
10
|
+
import { XmarkIcon } from '../icons-v2-generated/signs-and-symbols/xmark-icon'
|
|
11
|
+
import { ChatHeaderIconButton } from './chat-header-icon-button'
|
|
12
|
+
import { MoreActionsMenu } from '../ui/more-actions-menu'
|
|
13
|
+
|
|
14
|
+
export interface ChatPanelHeaderProps {
|
|
15
|
+
/** Show the back-chevron + bold (h3) title. When false, the static list
|
|
16
|
+
* title (h4) is shown with no back affordance. */
|
|
17
|
+
showBack?: boolean
|
|
18
|
+
/** Title text (next to the back chevron, or the static list title). */
|
|
19
|
+
title: string
|
|
20
|
+
/** Accessible label for the back chevron. */
|
|
21
|
+
backAriaLabel?: string
|
|
22
|
+
/** The open conversation is an archived chat (read-only). */
|
|
23
|
+
isArchivedView?: boolean
|
|
24
|
+
/** Back-chevron handler. */
|
|
25
|
+
onBack: () => void
|
|
26
|
+
/** Close the panel. */
|
|
27
|
+
onClose: () => void
|
|
28
|
+
/** Restore/unarchive — renders the refresh button (archived view only). */
|
|
29
|
+
onRestore?: () => void
|
|
30
|
+
/** Rename — adds the "Rename chat" item to the ⋯ menu. */
|
|
31
|
+
onRename?: () => void
|
|
32
|
+
/** Archive — adds the "Archive chat" item to the ⋯ menu. */
|
|
33
|
+
onArchive?: () => void
|
|
34
|
+
/** Open the Chat Archive page — renders the clock button (list view only). */
|
|
35
|
+
onOpenArchive?: () => void
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Chat panel top-navigation (Figma node 7363:205930). One bar across the
|
|
40
|
+
* list / active-conversation / archived-conversation / guide views: a
|
|
41
|
+
* back-chevron + title (or the static list title), then state-dependent
|
|
42
|
+
* right-hand actions (restore, ⋯ rename/archive, archive entry) and close.
|
|
43
|
+
*/
|
|
44
|
+
export function ChatPanelHeader({
|
|
45
|
+
showBack = false,
|
|
46
|
+
title,
|
|
47
|
+
backAriaLabel = 'Back',
|
|
48
|
+
isArchivedView = false,
|
|
49
|
+
onBack,
|
|
50
|
+
onClose,
|
|
51
|
+
onRestore,
|
|
52
|
+
onRename,
|
|
53
|
+
onArchive,
|
|
54
|
+
onOpenArchive,
|
|
55
|
+
}: ChatPanelHeaderProps) {
|
|
56
|
+
const menuItems = [
|
|
57
|
+
onRename && { label: 'Rename chat', onClick: onRename },
|
|
58
|
+
onArchive && { label: 'Archive chat', onClick: onArchive },
|
|
59
|
+
].filter(Boolean) as { label: string; onClick: () => void }[]
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="flex-shrink-0 flex h-14 w-full overflow-hidden border-b border-ods-border bg-ods-card">
|
|
63
|
+
<div className="flex flex-1 min-w-0 items-center gap-2 px-4 py-3">
|
|
64
|
+
{showBack ? (
|
|
65
|
+
<>
|
|
66
|
+
<button
|
|
67
|
+
type="button"
|
|
68
|
+
onClick={onBack}
|
|
69
|
+
aria-label={backAriaLabel}
|
|
70
|
+
className="inline-flex shrink-0 items-center justify-center size-8 -ml-1 rounded-md text-ods-text-secondary transition-colors hover:bg-ods-bg-hover hover:text-ods-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-ods-accent"
|
|
71
|
+
>
|
|
72
|
+
<Chevron01LeftIcon size={20} />
|
|
73
|
+
</button>
|
|
74
|
+
<span className="truncate text-h3 text-ods-text-primary">{title}</span>
|
|
75
|
+
</>
|
|
76
|
+
) : (
|
|
77
|
+
<p className="truncate text-h4 text-ods-text-primary">{title}</p>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
{/* Restore (refresh) — archived chat header (Figma node 7361:425441). */}
|
|
82
|
+
{isArchivedView && onRestore && (
|
|
83
|
+
<ChatHeaderIconButton onClick={onRestore} aria-label="Unarchive chat">
|
|
84
|
+
<Refresh01LeftIcon size={24} />
|
|
85
|
+
</ChatHeaderIconButton>
|
|
86
|
+
)}
|
|
87
|
+
|
|
88
|
+
{/* Rename / Archive menu — active (non-archived) conversation only. */}
|
|
89
|
+
{showBack && !isArchivedView && menuItems.length > 0 && (
|
|
90
|
+
<MoreActionsMenu
|
|
91
|
+
ariaLabel="Chat actions"
|
|
92
|
+
onCloseAutoFocus={(e) => e.preventDefault()}
|
|
93
|
+
items={menuItems}
|
|
94
|
+
trigger={
|
|
95
|
+
<ChatHeaderIconButton aria-label="Chat actions">
|
|
96
|
+
<Ellipsis01Icon size={24} />
|
|
97
|
+
</ChatHeaderIconButton>
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
)}
|
|
101
|
+
|
|
102
|
+
{/* Chat Archive entry (Figma node 7532:225034) — list view only. */}
|
|
103
|
+
{!showBack && onOpenArchive && (
|
|
104
|
+
<ChatHeaderIconButton onClick={onOpenArchive} aria-label="Chat archive">
|
|
105
|
+
<ClockHistoryIcon size={24} />
|
|
106
|
+
</ChatHeaderIconButton>
|
|
107
|
+
)}
|
|
108
|
+
|
|
109
|
+
<ChatHeaderIconButton onClick={onClose} aria-label="Close">
|
|
110
|
+
<XmarkIcon size={24} />
|
|
111
|
+
</ChatHeaderIconButton>
|
|
112
|
+
</div>
|
|
113
|
+
)
|
|
114
|
+
}
|