@flamingo-stack/openframe-frontend-core 0.0.217 → 0.0.218
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-L6IBKPVM.js → chunk-EKBM4FHK.js} +2 -2
- package/dist/{chunk-SWZUZYWR.js → chunk-EWA2NFUR.js} +2 -2
- package/dist/{chunk-TYIBMDUZ.cjs → chunk-FZZBCRID.cjs} +7 -7
- package/dist/{chunk-TYIBMDUZ.cjs.map → chunk-FZZBCRID.cjs.map} +1 -1
- package/dist/{chunk-G2HHSZ3S.cjs → chunk-GE64T3JT.cjs} +9 -9
- package/dist/{chunk-G2HHSZ3S.cjs.map → chunk-GE64T3JT.cjs.map} +1 -1
- package/dist/{chunk-YWDC5BXM.cjs → chunk-L5RSJE2I.cjs} +1940 -915
- package/dist/chunk-L5RSJE2I.cjs.map +1 -0
- package/dist/{chunk-BVFRD34B.js → chunk-OHOUSDAY.js} +2 -2
- package/dist/{chunk-MVQ3OODK.cjs → chunk-S4SVD5JI.cjs} +9 -9
- package/dist/{chunk-MVQ3OODK.cjs.map → chunk-S4SVD5JI.cjs.map} +1 -1
- package/dist/{chunk-N5IKPYRL.js → chunk-SWIR5EB2.js} +2 -2
- package/dist/{chunk-6DCKL73F.cjs → chunk-TCJ5B2ZD.cjs} +24 -24
- package/dist/{chunk-6DCKL73F.cjs.map → chunk-TCJ5B2ZD.cjs.map} +1 -1
- package/dist/{chunk-ENBGG2K2.js → chunk-V5JY5RSY.js} +2954 -1929
- package/dist/chunk-V5JY5RSY.js.map +1 -0
- package/dist/components/chat/embeddable-chat.d.ts +13 -0
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts +104 -10
- package/dist/components/chat/hooks/use-nats-chat-adapter.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-slash-commands.d.ts +6 -0
- package/dist/components/chat/hooks/use-slash-commands.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 +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/types/unified-chat-state.types.d.ts +81 -0
- package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/index.cjs +73 -51
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +26 -4
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/app-header.d.ts +7 -0
- package/dist/components/navigation/app-header.d.ts.map +1 -1
- package/dist/components/navigation/app-layout-drawer.d.ts +65 -0
- package/dist/components/navigation/app-layout-drawer.d.ts.map +1 -0
- package/dist/components/navigation/app-layout.d.ts +9 -1
- package/dist/components/navigation/app-layout.d.ts.map +1 -1
- package/dist/components/navigation/header-mingo-button.d.ts +21 -0
- package/dist/components/navigation/header-mingo-button.d.ts.map +1 -0
- package/dist/components/navigation/index.cjs +24 -2
- package/dist/components/navigation/index.cjs.map +1 -1
- package/dist/components/navigation/index.d.ts +5 -1
- package/dist/components/navigation/index.d.ts.map +1 -1
- package/dist/components/navigation/index.js +23 -1
- package/dist/components/onboarding-guides/index.cjs +18 -18
- package/dist/components/onboarding-guides/index.js +3 -3
- package/dist/components/tickets/hooks/use-ticket-engagements.d.ts.map +1 -1
- package/dist/components/tickets/index.cjs +80 -66
- package/dist/components/tickets/index.cjs.map +1 -1
- package/dist/components/tickets/index.js +20 -6
- package/dist/components/tickets/index.js.map +1 -1
- package/dist/components/ui/index.cjs +2 -2
- package/dist/components/ui/index.js +1 -1
- package/dist/index.cjs +26 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +25 -1
- package/dist/utils/embed-authed-fetch.d.ts +80 -0
- package/dist/utils/embed-authed-fetch.d.ts.map +1 -1
- package/dist/utils/index.cjs +70 -5
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +70 -6
- package/dist/utils/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/chat/embeddable-chat.tsx +154 -37
- package/src/components/chat/hooks/use-nats-chat-adapter.ts +601 -23
- package/src/components/chat/hooks/use-slash-commands.ts +10 -1
- package/src/components/chat/hooks/use-sse-chat-adapter.ts +45 -0
- package/src/components/chat/hooks/use-unified-chat.ts +59 -0
- package/src/components/chat/types/unified-chat-state.types.ts +116 -0
- package/src/components/navigation/app-header.tsx +23 -0
- package/src/components/navigation/app-layout-drawer.tsx +620 -0
- package/src/components/navigation/app-layout.tsx +65 -26
- package/src/components/navigation/header-mingo-button.tsx +58 -0
- package/src/components/navigation/index.ts +17 -1
- package/src/components/tickets/hooks/use-ticket-engagements.ts +24 -4
- package/src/stories/AppLayoutDrawer.stories.tsx +228 -0
- package/src/utils/.embed-authed-fetch.md +7 -0
- package/src/utils/__tests__/embed-authed-fetch.test.ts +103 -1
- package/src/utils/embed-authed-fetch.ts +247 -7
- package/src/utils/index.ts +5 -1
- package/dist/chunk-ENBGG2K2.js.map +0 -1
- package/dist/chunk-YWDC5BXM.cjs.map +0 -1
- /package/dist/{chunk-L6IBKPVM.js.map → chunk-EKBM4FHK.js.map} +0 -0
- /package/dist/{chunk-SWZUZYWR.js.map → chunk-EWA2NFUR.js.map} +0 -0
- /package/dist/{chunk-BVFRD34B.js.map → chunk-OHOUSDAY.js.map} +0 -0
- /package/dist/{chunk-N5IKPYRL.js.map → chunk-SWIR5EB2.js.map} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flamingo-stack/openframe-frontend-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.218",
|
|
4
4
|
"description": "Shared design system and components for all Flamingo platforms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"test:ui": "vitest --ui",
|
|
192
192
|
"test:run": "vitest run",
|
|
193
193
|
"test:coverage": "vitest run --coverage",
|
|
194
|
-
"yalc:watch": "NODE_OPTIONS='--max-old-space-size=4096' nodemon --watch src --watch tsconfig.json --watch tsup.config.ts --watch tailwind.config.ts --watch package.json -e ts,tsx,json,css --ignore dist --ignore node_modules --ignore '*.lock' --ignore .yalc --ignore yalc.lock --exec 'rm -rf dist && tsup && yalc push --changed'",
|
|
194
|
+
"yalc:watch": "NODE_OPTIONS='--max-old-space-size=4096' nodemon --watch src --watch tsconfig.json --watch tsup.config.ts --watch tailwind.config.ts --watch package.json -e ts,tsx,json,css --ignore dist --ignore node_modules --ignore '*.lock' --ignore .yalc --ignore yalc.lock --exec 'rm -rf dist && tsup && tsc -p tsconfig.declarations.json && yalc push --changed'",
|
|
195
195
|
"yalc:push": "yalc push",
|
|
196
196
|
"yalc:publish": "yalc publish",
|
|
197
197
|
"generate:icons": "node scripts/generate-icons.mjs",
|
|
@@ -47,6 +47,7 @@ import { XmarkIcon } from '../icons-v2-generated/signs-and-symbols/xmark-icon'
|
|
|
47
47
|
|
|
48
48
|
import { ChatFooter } from './chat-container'
|
|
49
49
|
import { ChatInput } from './chat-input'
|
|
50
|
+
import { ChatSidebar } from './chat-sidebar'
|
|
50
51
|
import { MingoOnboardingCard } from './mingo-onboarding-card'
|
|
51
52
|
import { MingoOnboardingCardSkeleton } from './mingo-onboarding-card-skeleton'
|
|
52
53
|
import { ChatMessageList } from './chat-message-list'
|
|
@@ -167,6 +168,20 @@ export interface EmbeddableChatProps {
|
|
|
167
168
|
* else `'mingo'`.
|
|
168
169
|
*/
|
|
169
170
|
defaultActiveMode?: ChatMode
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Wrapper shell around the chat body.
|
|
174
|
+
* - `'drawer'` (default): wraps in a body-level Radix Drawer (slide-in
|
|
175
|
+
* overlay from the right) — the original MPH / standalone behaviour.
|
|
176
|
+
* - `'none'`: no shell. Renders only the chat body so the consumer can
|
|
177
|
+
* host it inside their own container (e.g. `AppLayoutDrawerContent`).
|
|
178
|
+
* The internal "Ask AI" trigger and iOS body scroll-lock are also
|
|
179
|
+
* suppressed — those are Drawer-shell concerns. The consumer is
|
|
180
|
+
* responsible for mount/unmount and for opening/closing via the
|
|
181
|
+
* `open` / `onOpenChange` props (which the in-body close button still
|
|
182
|
+
* drives).
|
|
183
|
+
*/
|
|
184
|
+
shell?: 'drawer' | 'none'
|
|
170
185
|
}
|
|
171
186
|
|
|
172
187
|
// =============================================================================
|
|
@@ -562,7 +577,13 @@ function EmbeddableChatInner({
|
|
|
562
577
|
activeMode: controlledActiveMode,
|
|
563
578
|
onActiveModeChange,
|
|
564
579
|
defaultActiveMode,
|
|
580
|
+
shell = 'drawer',
|
|
565
581
|
}: EmbeddableChatProps) {
|
|
582
|
+
// `shell === 'none'` means the consumer hosts us inside their own panel
|
|
583
|
+
// (e.g. AppLayoutDrawer in openframe-frontend). Several drawer-shell
|
|
584
|
+
// concerns are unconditional in this codebase — gate them off here so
|
|
585
|
+
// we don't double-up with the host's behaviour.
|
|
586
|
+
const shellLess = shell === 'none'
|
|
566
587
|
const runtime = useRequiredChatRuntime()
|
|
567
588
|
const source = runtime.source as DocSource
|
|
568
589
|
const commandsUrl = runtime.endpoints.commandsUrl
|
|
@@ -603,12 +624,15 @@ function EmbeddableChatInner({
|
|
|
603
624
|
|
|
604
625
|
// iOS scroll-lock — react-aria's two-layer approach plus body fixed-pos.
|
|
605
626
|
// See hub original for the long mechanism comment; logic copied verbatim.
|
|
606
|
-
|
|
627
|
+
// Skipped in shell-less mode: the host (AppLayoutDrawer) is in-layout, so
|
|
628
|
+
// there's no body-level overlay that should block page scrolling.
|
|
629
|
+
usePreventScroll({ isDisabled: !isOpen || shellLess })
|
|
607
630
|
|
|
608
631
|
const navigatingAwayRef = useRef(false)
|
|
609
632
|
|
|
610
633
|
useEffect(() => {
|
|
611
634
|
if (!isOpen) return
|
|
635
|
+
if (shellLess) return
|
|
612
636
|
if (typeof window === 'undefined') return
|
|
613
637
|
if (!isIOS()) return
|
|
614
638
|
|
|
@@ -634,7 +658,7 @@ function EmbeddableChatInner({
|
|
|
634
658
|
if (window.location.pathname !== openPathname) return
|
|
635
659
|
window.scrollTo(0, scrollY)
|
|
636
660
|
}
|
|
637
|
-
}, [isOpen])
|
|
661
|
+
}, [isOpen, shellLess])
|
|
638
662
|
|
|
639
663
|
// Imperative handle to the chat input.
|
|
640
664
|
const chatInputRef = useRef<ChatInputRef | null>(null)
|
|
@@ -755,8 +779,46 @@ function EmbeddableChatInner({
|
|
|
755
779
|
currentCacheHitRatePct,
|
|
756
780
|
currentUsageBreakdown,
|
|
757
781
|
displayRef,
|
|
782
|
+
// ─── Dialog management (Mingo-mode sidebar) ───
|
|
783
|
+
dialogs,
|
|
784
|
+
activeDialogId,
|
|
785
|
+
selectDialog,
|
|
786
|
+
startNewDialog,
|
|
787
|
+
isDialogsLoading,
|
|
788
|
+
hasMoreDialogs,
|
|
789
|
+
loadMoreDialogs,
|
|
758
790
|
} = useUnifiedChat({ modes: effectiveModes, activeMode })
|
|
759
791
|
|
|
792
|
+
// Whether the in-panel dialog sidebar should render. Gated on:
|
|
793
|
+
// 1. Mingo mode is active (Guide has localStorage-only history that
|
|
794
|
+
// isn't yet structured as a sidebar list — see
|
|
795
|
+
// [[chat-architecture-and-migration]] for the asymmetry).
|
|
796
|
+
// 2. The host wired `fetchDialogs` — managed-dialog mode, not the
|
|
797
|
+
// bare-transport Tauri flow.
|
|
798
|
+
const showSidebar =
|
|
799
|
+
activeMode === 'mingo' && effectiveModes.mingo?.fetchDialogs !== undefined
|
|
800
|
+
|
|
801
|
+
// Pending startNewDialog promise — used to gate the "Start new chat"
|
|
802
|
+
// button while creation is in flight so a double-click doesn't spawn
|
|
803
|
+
// two backend dialogs.
|
|
804
|
+
const [isStartingNewDialog, setIsStartingNewDialog] = useState<boolean>(false)
|
|
805
|
+
const handleStartNewDialog = useCallback(async () => {
|
|
806
|
+
if (isStartingNewDialog) return
|
|
807
|
+
setIsStartingNewDialog(true)
|
|
808
|
+
try {
|
|
809
|
+
await startNewDialog()
|
|
810
|
+
} finally {
|
|
811
|
+
setIsStartingNewDialog(false)
|
|
812
|
+
}
|
|
813
|
+
}, [isStartingNewDialog, startNewDialog])
|
|
814
|
+
|
|
815
|
+
const handleSelectDialog = useCallback(
|
|
816
|
+
(id: string) => {
|
|
817
|
+
selectDialog(id)
|
|
818
|
+
},
|
|
819
|
+
[selectDialog],
|
|
820
|
+
)
|
|
821
|
+
|
|
760
822
|
// Chat-attachment hooks (v2 attachment feature).
|
|
761
823
|
const {
|
|
762
824
|
attachments: stagedAttachments,
|
|
@@ -930,8 +992,9 @@ function EmbeddableChatInner({
|
|
|
930
992
|
return (
|
|
931
993
|
<>
|
|
932
994
|
{/* Floating "Ask AI" button — sticky-dock pattern. See hub original
|
|
933
|
-
for the full mechanism explanation.
|
|
934
|
-
|
|
995
|
+
for the full mechanism explanation. Suppressed in shell-less mode:
|
|
996
|
+
the host controls open/close, so an internal trigger would race. */}
|
|
997
|
+
{showInternalTrigger && !shellLess && (
|
|
935
998
|
<div
|
|
936
999
|
aria-hidden={isOpen}
|
|
937
1000
|
className={`sticky bottom-0 h-0 z-[9990] pointer-events-none ${
|
|
@@ -953,36 +1016,17 @@ function EmbeddableChatInner({
|
|
|
953
1016
|
</div>
|
|
954
1017
|
)}
|
|
955
1018
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
flush
|
|
968
|
-
resizable
|
|
969
|
-
minSize={480}
|
|
970
|
-
maxSize={1280}
|
|
971
|
-
defaultSize={640}
|
|
972
|
-
storageKey="mingo-chat-width"
|
|
973
|
-
resizeAriaLabel="Resize chat panel"
|
|
974
|
-
overlayClassName="mingo-chat-overlay md:bg-black/20"
|
|
975
|
-
aria-describedby={undefined}
|
|
976
|
-
className="
|
|
977
|
-
mingo-chat-content !bg-ods-bg shadow-2xl
|
|
978
|
-
focus:outline-none focus-visible:outline-none
|
|
979
|
-
w-screen md:w-auto
|
|
980
|
-
"
|
|
981
|
-
>
|
|
982
|
-
<VisuallyHidden>
|
|
983
|
-
<DialogPrimitive.Title>{sourceLabel} AI Assistant</DialogPrimitive.Title>
|
|
984
|
-
</VisuallyHidden>
|
|
985
|
-
|
|
1019
|
+
{/*
|
|
1020
|
+
Conditional shell — overlay (Drawer, MPH default) vs inline
|
|
1021
|
+
(positioned `<aside>` anchored to the nearest positioned
|
|
1022
|
+
ancestor, openframe-frontend's nav-embedded chat). Both share
|
|
1023
|
+
the same `body` JSX so the chat content is defined exactly
|
|
1024
|
+
once; the IIFE keeps both branches type-balanced inside JSX
|
|
1025
|
+
(no opening tag in one ternary branch + closing in another).
|
|
1026
|
+
*/}
|
|
1027
|
+
{(() => {
|
|
1028
|
+
const body = (
|
|
1029
|
+
<>
|
|
986
1030
|
<div className="flex h-full flex-col overflow-hidden">
|
|
987
1031
|
{/* Figma node 7363:205930 — top-navigation. Title intentionally
|
|
988
1032
|
omitted; a chevron-left + "New Chat" back-style affordance
|
|
@@ -1021,6 +1065,27 @@ function EmbeddableChatInner({
|
|
|
1021
1065
|
</button>
|
|
1022
1066
|
</div>
|
|
1023
1067
|
|
|
1068
|
+
{/* Sidebar + chat-panel row. When Mingo is the active mode and
|
|
1069
|
+
`fetchDialogs` is wired, the in-panel `<ChatSidebar>` lists
|
|
1070
|
+
the user's backend-driven dialog history. Guide mode keeps
|
|
1071
|
+
history in localStorage and currently renders no sidebar. */}
|
|
1072
|
+
<div className="flex flex-1 min-h-0 overflow-hidden">
|
|
1073
|
+
{showSidebar && (
|
|
1074
|
+
<ChatSidebar
|
|
1075
|
+
className="w-72 shrink-0"
|
|
1076
|
+
dialogs={dialogs}
|
|
1077
|
+
activeDialogId={activeDialogId ?? undefined}
|
|
1078
|
+
onDialogSelect={handleSelectDialog}
|
|
1079
|
+
onNewChat={() => { void handleStartNewDialog() }}
|
|
1080
|
+
isLoading={isDialogsLoading && dialogs.length === 0}
|
|
1081
|
+
isCreatingDialog={isStartingNewDialog}
|
|
1082
|
+
hasNextPage={hasMoreDialogs}
|
|
1083
|
+
isFetchingNextPage={isDialogsLoading && dialogs.length > 0}
|
|
1084
|
+
onLoadMore={() => { void loadMoreDialogs() }}
|
|
1085
|
+
/>
|
|
1086
|
+
)}
|
|
1087
|
+
<div className="flex flex-1 flex-col min-h-0 min-w-0">
|
|
1088
|
+
|
|
1024
1089
|
{showModeToggle ? (
|
|
1025
1090
|
<div
|
|
1026
1091
|
role="radiogroup"
|
|
@@ -1222,11 +1287,63 @@ function EmbeddableChatInner({
|
|
|
1222
1287
|
</div>
|
|
1223
1288
|
</div>
|
|
1224
1289
|
</div>
|
|
1290
|
+
</div>
|
|
1291
|
+
</div>
|
|
1225
1292
|
</div>
|
|
1226
1293
|
{galleryModal}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1294
|
+
</>
|
|
1295
|
+
)
|
|
1296
|
+
|
|
1297
|
+
// Shell-less branch — host (e.g. AppLayoutDrawer) provides the panel
|
|
1298
|
+
// chrome, focus trap, animation, and size. We render only the chat
|
|
1299
|
+
// body plus ChatPanelContext so descendants can still close after
|
|
1300
|
+
// same-tab navigation via the host's `onOpenChange`.
|
|
1301
|
+
if (shellLess) {
|
|
1302
|
+
return (
|
|
1303
|
+
<ChatPanelContext.Provider value={chatPanelHandle}>
|
|
1304
|
+
{body}
|
|
1305
|
+
</ChatPanelContext.Provider>
|
|
1306
|
+
)
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
// Body-level Radix Drawer — backdrop, iOS scroll-lock, focus
|
|
1310
|
+
// trap, drag-to-resize handle. Slides in from the right edge.
|
|
1311
|
+
return (
|
|
1312
|
+
<Drawer open={isOpen} onOpenChange={(o: boolean) => !o && handleClose()}>
|
|
1313
|
+
<ChatPanelContext.Provider value={chatPanelHandle}>
|
|
1314
|
+
{/*
|
|
1315
|
+
Panel-level handle for descendants (inline cards via
|
|
1316
|
+
`ChatCardNavWrap`, markdown-body links via
|
|
1317
|
+
`NavLinkAnchorViaRuntime`) to close the panel after same-tab
|
|
1318
|
+
navigation. Same-tab clicks fire `closeChat`; new-tab clicks
|
|
1319
|
+
leave the panel open while the new tab loads.
|
|
1320
|
+
*/}
|
|
1321
|
+
<DrawerContent
|
|
1322
|
+
side="right"
|
|
1323
|
+
flush
|
|
1324
|
+
resizable
|
|
1325
|
+
minSize={showSidebar ? 720 : 480}
|
|
1326
|
+
maxSize={1600}
|
|
1327
|
+
defaultSize={showSidebar ? 960 : 640}
|
|
1328
|
+
storageKey={showSidebar ? 'mingo-chat-width-with-sidebar' : 'mingo-chat-width'}
|
|
1329
|
+
resizeAriaLabel="Resize chat panel"
|
|
1330
|
+
overlayClassName="mingo-chat-overlay md:bg-black/20"
|
|
1331
|
+
aria-describedby={undefined}
|
|
1332
|
+
className="
|
|
1333
|
+
mingo-chat-content !bg-ods-bg shadow-2xl
|
|
1334
|
+
focus:outline-none focus-visible:outline-none
|
|
1335
|
+
w-screen md:w-auto
|
|
1336
|
+
"
|
|
1337
|
+
>
|
|
1338
|
+
<VisuallyHidden>
|
|
1339
|
+
<DialogPrimitive.Title>{sourceLabel} AI Assistant</DialogPrimitive.Title>
|
|
1340
|
+
</VisuallyHidden>
|
|
1341
|
+
{body}
|
|
1342
|
+
</DrawerContent>
|
|
1343
|
+
</ChatPanelContext.Provider>
|
|
1344
|
+
</Drawer>
|
|
1345
|
+
)
|
|
1346
|
+
})()}
|
|
1230
1347
|
</>
|
|
1231
1348
|
)
|
|
1232
1349
|
}
|