@hanzo/ui 8.0.28 → 8.0.31
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/backends/gui/slot.cjs +11 -1
- package/dist/backends/gui/slot.d.ts +9 -0
- package/dist/backends/gui/slot.d.ts.map +1 -1
- package/dist/backends/gui/slot.js +9 -0
- package/dist/backends/gui/slot.js.map +1 -1
- package/dist/backends/gui/textarea.cjs +0 -8
- package/dist/backends/gui/textarea.d.ts +8 -1
- package/dist/backends/gui/textarea.d.ts.map +1 -1
- package/dist/backends/gui/textarea.js +0 -8
- package/dist/backends/gui/textarea.js.map +1 -1
- package/dist/chat/Code.cjs +70 -0
- package/dist/chat/Code.d.ts +25 -0
- package/dist/chat/Code.d.ts.map +1 -0
- package/dist/chat/Code.js +67 -0
- package/dist/chat/Code.js.map +1 -0
- package/dist/chat/Composer.cjs +56 -0
- package/dist/chat/Composer.d.ts +30 -0
- package/dist/chat/Composer.d.ts.map +1 -0
- package/dist/chat/Composer.js +53 -0
- package/dist/chat/Composer.js.map +1 -0
- package/dist/chat/Header.cjs +49 -0
- package/dist/chat/Header.d.ts +46 -0
- package/dist/chat/Header.d.ts.map +1 -0
- package/dist/chat/Header.js +43 -0
- package/dist/chat/Header.js.map +1 -0
- package/dist/chat/Message.cjs +27 -0
- package/dist/chat/Message.d.ts +14 -0
- package/dist/chat/Message.d.ts.map +1 -0
- package/dist/chat/Message.js +25 -0
- package/dist/chat/Message.js.map +1 -0
- package/dist/chat/Sidebar.cjs +81 -0
- package/dist/chat/Sidebar.d.ts +79 -0
- package/dist/chat/Sidebar.d.ts.map +1 -0
- package/dist/chat/Sidebar.js +71 -0
- package/dist/chat/Sidebar.js.map +1 -0
- package/dist/chat/Sources.cjs +25 -0
- package/dist/chat/Sources.d.ts +23 -0
- package/dist/chat/Sources.d.ts.map +1 -0
- package/dist/chat/Sources.js +22 -0
- package/dist/chat/Sources.js.map +1 -0
- package/dist/chat/Thread.cjs +42 -0
- package/dist/chat/Thread.d.ts +11 -0
- package/dist/chat/Thread.d.ts.map +1 -0
- package/dist/chat/Thread.js +40 -0
- package/dist/chat/Thread.js.map +1 -0
- package/dist/chat/index.cjs +58 -0
- package/dist/chat/index.d.ts +30 -0
- package/dist/chat/index.d.ts.map +1 -0
- package/dist/chat/index.js +30 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/send.cjs +44 -0
- package/dist/chat/send.d.ts +32 -0
- package/dist/chat/send.d.ts.map +1 -0
- package/dist/chat/send.js +40 -0
- package/dist/chat/send.js.map +1 -0
- package/dist/chat/stick.cjs +19 -0
- package/dist/chat/stick.d.ts +24 -0
- package/dist/chat/stick.d.ts.map +1 -0
- package/dist/chat/stick.js +16 -0
- package/dist/chat/stick.js.map +1 -0
- package/package.json +8 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Message = Message;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
/**
|
|
7
|
+
* Message — one turn in a thread.
|
|
8
|
+
*
|
|
9
|
+
* Role drives presentation and nothing else: a user turn is a contained bubble
|
|
10
|
+
* that shrinks to its content, an assistant turn is full-bleed prose, a system
|
|
11
|
+
* turn is a muted aside. Content is `children`, so the surface keeps its own
|
|
12
|
+
* markdown pipeline — the surfaces disagree on remark plugins and none of that
|
|
13
|
+
* belongs in a presentational package.
|
|
14
|
+
*/
|
|
15
|
+
const gui_1 = require("@hanzo/gui");
|
|
16
|
+
const slot_1 = require("../backends/gui/slot.cjs");
|
|
17
|
+
function Message({ role, children, actions, busy = false, icon }) {
|
|
18
|
+
if (role === 'system')
|
|
19
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('message'), "data-role": "system", width: "100%", justify: "center", py: "$2", children: (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", text: "center", children: children }) }));
|
|
20
|
+
const mine = role === 'user';
|
|
21
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('message'), "data-role": role, width: "100%", justify: mine ? 'flex-end' : 'flex-start', gap: "$2", children: [icon && !mine ? (0, jsx_runtime_1.jsx)(gui_1.YStack, { pt: "$1", children: icon }) : null, (0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('message-body'), "data-bubble": mine ? 'true' : undefined, gap: "$2", maxW: mine ? '80%' : '100%', flex: mine ? undefined : 1, ...(mine && {
|
|
22
|
+
bg: '$color3',
|
|
23
|
+
rounded: '$5',
|
|
24
|
+
px: '$3',
|
|
25
|
+
py: '$2',
|
|
26
|
+
}), children: [children, busy ? (0, jsx_runtime_1.jsx)(gui_1.SizableText, { ...(0, slot_1.slot)('message-busy'), size: "$2", color: "$color10", children: "\u2026" }) : null, actions ? (0, jsx_runtime_1.jsx)(gui_1.XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export type Role = 'user' | 'assistant' | 'system';
|
|
3
|
+
export interface MessageProps {
|
|
4
|
+
role: Role;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
/** Row rendered under the turn — copy, retry, feedback. */
|
|
7
|
+
actions?: ReactNode;
|
|
8
|
+
/** The turn is still streaming. */
|
|
9
|
+
busy?: boolean;
|
|
10
|
+
/** Leading affordance for an assistant turn: avatar or model mark. */
|
|
11
|
+
icon?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export declare function Message({ role, children, actions, busy, icon }: MessageProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=Message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAA;AAElD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,mCAAmC;IACnC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,wBAAgB,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAY,EAAE,IAAI,EAAE,EAAE,YAAY,2CAuCpF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Message — one turn in a thread.
|
|
5
|
+
*
|
|
6
|
+
* Role drives presentation and nothing else: a user turn is a contained bubble
|
|
7
|
+
* that shrinks to its content, an assistant turn is full-bleed prose, a system
|
|
8
|
+
* turn is a muted aside. Content is `children`, so the surface keeps its own
|
|
9
|
+
* markdown pipeline — the surfaces disagree on remark plugins and none of that
|
|
10
|
+
* belongs in a presentational package.
|
|
11
|
+
*/
|
|
12
|
+
import { SizableText, Text, XStack, YStack } from '@hanzo/gui';
|
|
13
|
+
import { slot } from '../backends/gui/slot.js';
|
|
14
|
+
export function Message({ role, children, actions, busy = false, icon }) {
|
|
15
|
+
if (role === 'system')
|
|
16
|
+
return (_jsx(XStack, { ...slot('message'), "data-role": "system", width: "100%", justify: "center", py: "$2", children: _jsx(Text, { fontSize: "$1", color: "$color10", text: "center", children: children }) }));
|
|
17
|
+
const mine = role === 'user';
|
|
18
|
+
return (_jsxs(XStack, { ...slot('message'), "data-role": role, width: "100%", justify: mine ? 'flex-end' : 'flex-start', gap: "$2", children: [icon && !mine ? _jsx(YStack, { pt: "$1", children: icon }) : null, _jsxs(YStack, { ...slot('message-body'), "data-bubble": mine ? 'true' : undefined, gap: "$2", maxW: mine ? '80%' : '100%', flex: mine ? undefined : 1, ...(mine && {
|
|
19
|
+
bg: '$color3',
|
|
20
|
+
rounded: '$5',
|
|
21
|
+
px: '$3',
|
|
22
|
+
py: '$2',
|
|
23
|
+
}), children: [children, busy ? _jsx(SizableText, { ...slot('message-busy'), size: "$2", color: "$color10", children: "\u2026" }) : null, actions ? _jsx(XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=Message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Message.js","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;GAQG;AACH,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAG9D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAe3C,MAAM,UAAU,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,GAAG,KAAK,EAAE,IAAI,EAAgB;IACnF,IAAI,IAAI,KAAK,QAAQ;QACnB,OAAO,CACL,KAAC,MAAM,OAAK,IAAI,CAAC,SAAS,CAAC,eAAY,QAAQ,EAAC,KAAK,EAAC,MAAM,EAAC,OAAO,EAAC,QAAQ,EAAC,EAAE,EAAC,IAAI,YACnF,KAAC,IAAI,IAAC,QAAQ,EAAC,IAAI,EAAC,KAAK,EAAC,UAAU,EAAC,IAAI,EAAC,QAAQ,YAC/C,QAAQ,GACJ,GACA,CACV,CAAA;IAEH,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAA;IAC5B,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,eACR,IAAI,EACf,KAAK,EAAC,MAAM,EACZ,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,EACzC,GAAG,EAAC,IAAI,aAEP,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,EAAE,EAAC,IAAI,YAAE,IAAI,GAAU,CAAC,CAAC,CAAC,IAAI,EACvD,MAAC,MAAM,OACD,IAAI,CAAC,cAAc,CAAC,iBACX,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACtC,GAAG,EAAC,IAAI,EACR,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAC3B,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KACtB,CAAC,IAAI,IAAI;oBACX,EAAE,EAAE,SAAS;oBACb,OAAO,EAAE,IAAI;oBACb,EAAE,EAAE,IAAI;oBACR,EAAE,EAAE,IAAI;iBACT,CAAC,aAED,QAAQ,EACR,IAAI,CAAC,CAAC,CAAC,KAAC,WAAW,OAAK,IAAI,CAAC,cAAc,CAAC,EAAE,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,UAAU,uBAAgB,CAAC,CAAC,CAAC,IAAI,EAC/F,OAAO,CAAC,CAAC,CAAC,KAAC,MAAM,IAAC,GAAG,EAAC,IAAI,EAAC,KAAK,EAAC,QAAQ,YAAE,OAAO,GAAU,CAAC,CAAC,CAAC,IAAI,IAC7D,IACF,CACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use client';"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Sidebar = Sidebar;
|
|
5
|
+
exports.SidebarHeader = SidebarHeader;
|
|
6
|
+
exports.SidebarIconButton = SidebarIconButton;
|
|
7
|
+
exports.SidebarNewChat = SidebarNewChat;
|
|
8
|
+
exports.SidebarScroll = SidebarScroll;
|
|
9
|
+
exports.SidebarSection = SidebarSection;
|
|
10
|
+
exports.SidebarItem = SidebarItem;
|
|
11
|
+
exports.SidebarFolder = SidebarFolder;
|
|
12
|
+
exports.SidebarUser = SidebarUser;
|
|
13
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
14
|
+
/**
|
|
15
|
+
* Sidebar — conversation navigation for a chat surface.
|
|
16
|
+
*
|
|
17
|
+
* Composed of parts rather than fed a tree, because surfaces disagree about what
|
|
18
|
+
* a conversation list contains: hanzo.chat groups into folders, the console
|
|
19
|
+
* groups by project, hanzo.app shows a flat recents list. A `sections` prop
|
|
20
|
+
* would have to model all three; parts let each surface arrange its own and
|
|
21
|
+
* still get identical rows.
|
|
22
|
+
*
|
|
23
|
+
* Presentational: no routing, no fetching, no active-id resolution. `active` is
|
|
24
|
+
* passed in, `onPress` is raised out.
|
|
25
|
+
*/
|
|
26
|
+
const gui_1 = require("@hanzo/gui");
|
|
27
|
+
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
28
|
+
const react_1 = require("react");
|
|
29
|
+
const slot_1 = require("../backends/gui/slot.cjs");
|
|
30
|
+
const WIDTH = 264;
|
|
31
|
+
const ROW = { px: '$2', py: '$1.5', rounded: '$3' };
|
|
32
|
+
function Sidebar({ children, width = WIDTH }) {
|
|
33
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('sidebar'), width: width, shrink: 0, height: "100%", gap: "$1", p: "$2", bg: "$color2", borderRightWidth: 1, borderColor: "$borderColor", children: children }));
|
|
34
|
+
}
|
|
35
|
+
function SidebarHeader({ title, onOpenSwitcher, onSearch, onCollapse, }) {
|
|
36
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('sidebar-header'), items: "center", gap: "$1", px: "$1", py: "$1.5", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...ROW, items: "center", gap: "$1", shrink: 1, cursor: onOpenSwitcher ? 'pointer' : undefined, onPress: onOpenSwitcher, hoverStyle: onOpenSwitcher ? { bg: '$color4' } : undefined, pressStyle: onOpenSwitcher ? { bg: '$color5' } : undefined, children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$3", fontWeight: "600", numberOfLines: 1, children: title }), onOpenSwitcher ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 14, opacity: 0.6 }) : null] }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1 }), onSearch ? ((0, jsx_runtime_1.jsx)(SidebarIconButton, { label: "Search conversations", onPress: onSearch, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Search, { size: 16 }) })) : null, onCollapse ? ((0, jsx_runtime_1.jsx)(SidebarIconButton, { label: "Collapse sidebar", onPress: onCollapse, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.PanelLeft, { size: 16 }) })) : null] }));
|
|
37
|
+
}
|
|
38
|
+
function SidebarIconButton({ label, onPress, children }) {
|
|
39
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { width: 28, height: 28, items: "center", justify: "center", rounded: "$3", cursor: "pointer", opacity: 0.7, onPress: onPress, role: "button", tabIndex: 0, "aria-label": label, ...(0, slot_1.tip)(label), hoverStyle: { bg: '$color4', opacity: 1 }, pressStyle: { bg: '$color5' }, children: children }));
|
|
40
|
+
}
|
|
41
|
+
function SidebarNewChat({ label = 'New chat', onPress }) {
|
|
42
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('sidebar-new-chat'), ...ROW, items: "center", gap: "$2", cursor: "pointer", onPress: onPress, role: "button", tabIndex: 0, hoverStyle: { bg: '$color4' }, pressStyle: { bg: '$color5' }, children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.SquarePen, { size: 16 }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", fontWeight: "500", children: label })] }));
|
|
43
|
+
}
|
|
44
|
+
/** SidebarScroll — the scrolling middle, so header and user chip stay pinned. */
|
|
45
|
+
function SidebarScroll({ children }) {
|
|
46
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.ScrollView, { ...(0, slot_1.slot)('sidebar-scroll'), flex: 1, showsVerticalScrollIndicator: false, children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { gap: "$0.5", children: children }) }));
|
|
47
|
+
}
|
|
48
|
+
function SidebarSection({ label, children }) {
|
|
49
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('sidebar-section'), mt: "$3", gap: "$0.5", children: [label ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", px: "$2", py: "$1", color: "$color10", fontWeight: "500", children: label })) : null, children] }));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* SidebarItem — one conversation.
|
|
53
|
+
*
|
|
54
|
+
* The title is clamped to a single line rather than wrapped: generated titles
|
|
55
|
+
* run long, and a wrapping row makes the list's scan height irregular while the
|
|
56
|
+
* first few words are what identify a conversation anyway.
|
|
57
|
+
*/
|
|
58
|
+
function SidebarItem({ children, active = false, onPress, icon }) {
|
|
59
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('sidebar-item'), ...ROW, items: "center", gap: "$2", cursor: "pointer", onPress: onPress, role: "button", tabIndex: 0, "aria-current": active ? 'page' : undefined, bg: active ? '$color4' : undefined, hoverStyle: { bg: active ? '$color4' : '$color3' }, pressStyle: { bg: '$color5' }, children: [icon ? (0, jsx_runtime_1.jsx)(gui_1.YStack, { opacity: 0.7, children: icon }) : null, (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", numberOfLines: 1, flex: 1, color: active ? '$color' : '$color11', children: children })] }));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* SidebarFolder — a collapsible group.
|
|
63
|
+
*
|
|
64
|
+
* Uncontrolled by default and controlled the moment `open` is supplied, so the
|
|
65
|
+
* common case needs no state while a surface that persists expansion can still
|
|
66
|
+
* drive it.
|
|
67
|
+
*/
|
|
68
|
+
function SidebarFolder({ name, children, defaultOpen = false, open: openProp, onOpenChange, }) {
|
|
69
|
+
const [own, setOwn] = (0, react_1.useState)(defaultOpen);
|
|
70
|
+
const controlled = openProp !== undefined;
|
|
71
|
+
const open = controlled ? openProp : own;
|
|
72
|
+
const toggle = () => {
|
|
73
|
+
if (!controlled)
|
|
74
|
+
setOwn((v) => !v);
|
|
75
|
+
onOpenChange?.(!open);
|
|
76
|
+
};
|
|
77
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('sidebar-folder'), children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...ROW, items: "center", gap: "$1.5", cursor: "pointer", onPress: toggle, role: "button", tabIndex: 0, "aria-expanded": open, hoverStyle: { bg: '$color3' }, pressStyle: { bg: '$color5' }, children: [open ? ((0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 14, opacity: 0.6 })) : ((0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronRight, { size: 14, opacity: 0.6 })), (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Folder, { size: 16, opacity: 0.7 }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", numberOfLines: 1, flex: 1, color: "$color11", children: name })] }), open ? ((0, jsx_runtime_1.jsx)(gui_1.YStack, { pl: "$4", gap: "$0.5", children: children })) : null] }));
|
|
78
|
+
}
|
|
79
|
+
function SidebarUser({ name, secondary, avatar, onPress, onHelp }) {
|
|
80
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('sidebar-user'), items: "center", gap: "$1", mt: "$1", pt: "$2", borderTopWidth: 1, borderColor: "$borderColor", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...ROW, items: "center", gap: "$2", flex: 1, cursor: "pointer", onPress: onPress, role: "button", tabIndex: 0, hoverStyle: { bg: '$color3' }, pressStyle: { bg: '$color5' }, children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { width: 24, height: 24, rounded: 9999, items: "center", justify: "center", bg: "$color5", overflow: "hidden", children: avatar ?? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", fontWeight: "600", children: name.charAt(0).toUpperCase() })) }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", numberOfLines: 1, children: name }), secondary ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color10", numberOfLines: 1, children: secondary })) : null] })] }), onHelp ? ((0, jsx_runtime_1.jsx)(SidebarIconButton, { label: "Help", onPress: onHelp, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.CircleHelp, { size: 16 }) })) : null] }));
|
|
81
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export interface SidebarProps {
|
|
3
|
+
children?: ReactNode;
|
|
4
|
+
/** Column width in px. */
|
|
5
|
+
width?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function Sidebar({ children, width }: SidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export interface SidebarHeaderProps {
|
|
9
|
+
/** Product name. Not the workspace or account — those belong in SidebarUser. */
|
|
10
|
+
title: string;
|
|
11
|
+
onOpenSwitcher?: () => void;
|
|
12
|
+
onSearch?: () => void;
|
|
13
|
+
onCollapse?: () => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function SidebarHeader({ title, onOpenSwitcher, onSearch, onCollapse, }: SidebarHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export interface SidebarIconButtonProps {
|
|
17
|
+
/**
|
|
18
|
+
* Required. Becomes the accessible name — an icon-only control without one is
|
|
19
|
+
* unreadable to a screen reader, and these controls are the whole navigation.
|
|
20
|
+
*/
|
|
21
|
+
label: string;
|
|
22
|
+
onPress?: () => void;
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
export declare function SidebarIconButton({ label, onPress, children }: SidebarIconButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export interface SidebarNewChatProps {
|
|
27
|
+
label?: string;
|
|
28
|
+
onPress?: () => void;
|
|
29
|
+
}
|
|
30
|
+
export declare function SidebarNewChat({ label, onPress }: SidebarNewChatProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
/** SidebarScroll — the scrolling middle, so header and user chip stay pinned. */
|
|
32
|
+
export declare function SidebarScroll({ children }: {
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
export interface SidebarSectionProps {
|
|
36
|
+
label?: string;
|
|
37
|
+
children?: ReactNode;
|
|
38
|
+
}
|
|
39
|
+
export declare function SidebarSection({ label, children }: SidebarSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export interface SidebarItemProps {
|
|
41
|
+
children?: ReactNode;
|
|
42
|
+
active?: boolean;
|
|
43
|
+
onPress?: () => void;
|
|
44
|
+
icon?: ReactNode;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* SidebarItem — one conversation.
|
|
48
|
+
*
|
|
49
|
+
* The title is clamped to a single line rather than wrapped: generated titles
|
|
50
|
+
* run long, and a wrapping row makes the list's scan height irregular while the
|
|
51
|
+
* first few words are what identify a conversation anyway.
|
|
52
|
+
*/
|
|
53
|
+
export declare function SidebarItem({ children, active, onPress, icon }: SidebarItemProps): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
export interface SidebarFolderProps {
|
|
55
|
+
name: string;
|
|
56
|
+
children?: ReactNode;
|
|
57
|
+
/** Uncontrolled initial state. Ignored when `open` is passed. */
|
|
58
|
+
defaultOpen?: boolean;
|
|
59
|
+
open?: boolean;
|
|
60
|
+
onOpenChange?: (open: boolean) => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* SidebarFolder — a collapsible group.
|
|
64
|
+
*
|
|
65
|
+
* Uncontrolled by default and controlled the moment `open` is supplied, so the
|
|
66
|
+
* common case needs no state while a surface that persists expansion can still
|
|
67
|
+
* drive it.
|
|
68
|
+
*/
|
|
69
|
+
export declare function SidebarFolder({ name, children, defaultOpen, open: openProp, onOpenChange, }: SidebarFolderProps): import("react/jsx-runtime").JSX.Element;
|
|
70
|
+
export interface SidebarUserProps {
|
|
71
|
+
name: string;
|
|
72
|
+
secondary?: string;
|
|
73
|
+
/** Avatar slot. Falls back to the first letter of `name`. */
|
|
74
|
+
avatar?: ReactNode;
|
|
75
|
+
onPress?: () => void;
|
|
76
|
+
onHelp?: () => void;
|
|
77
|
+
}
|
|
78
|
+
export declare function SidebarUser({ name, secondary, avatar, onPress, onHelp }: SidebarUserProps): import("react/jsx-runtime").JSX.Element;
|
|
79
|
+
//# sourceMappingURL=Sidebar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../src/chat/Sidebar.tsx"],"names":[],"mappings":"AAwBA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAOhD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,KAAa,EAAE,EAAE,YAAY,2CAgBhE;AAED,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;CACxB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,cAAc,EACd,QAAQ,EACR,UAAU,GACX,EAAE,kBAAkB,2CAgCpB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,sBAAsB,2CAqBrF;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAkB,EAAE,OAAO,EAAE,EAAE,mBAAmB,2CAoBlF;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,2CAMnE;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CAWtE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,MAAc,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAsBxF;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,QAAQ,EACR,WAAmB,EACnB,IAAI,EAAE,QAAQ,EACd,YAAY,GACb,EAAE,kBAAkB,2CAyCpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAwDzF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Sidebar — conversation navigation for a chat surface.
|
|
5
|
+
*
|
|
6
|
+
* Composed of parts rather than fed a tree, because surfaces disagree about what
|
|
7
|
+
* a conversation list contains: hanzo.chat groups into folders, the console
|
|
8
|
+
* groups by project, hanzo.app shows a flat recents list. A `sections` prop
|
|
9
|
+
* would have to model all three; parts let each surface arrange its own and
|
|
10
|
+
* still get identical rows.
|
|
11
|
+
*
|
|
12
|
+
* Presentational: no routing, no fetching, no active-id resolution. `active` is
|
|
13
|
+
* passed in, `onPress` is raised out.
|
|
14
|
+
*/
|
|
15
|
+
import { ScrollView, SizableText, XStack, YStack } from '@hanzo/gui';
|
|
16
|
+
import { ChevronDown, ChevronRight, CircleHelp, Folder, PanelLeft, Search, SquarePen, } from '@hanzogui/lucide-icons-2';
|
|
17
|
+
import { useState } from 'react';
|
|
18
|
+
import { slot, tip } from '../backends/gui/slot.js';
|
|
19
|
+
const WIDTH = 264;
|
|
20
|
+
const ROW = { px: '$2', py: '$1.5', rounded: '$3' };
|
|
21
|
+
export function Sidebar({ children, width = WIDTH }) {
|
|
22
|
+
return (_jsx(YStack, { ...slot('sidebar'), width: width, shrink: 0, height: "100%", gap: "$1", p: "$2", bg: "$color2", borderRightWidth: 1, borderColor: "$borderColor", children: children }));
|
|
23
|
+
}
|
|
24
|
+
export function SidebarHeader({ title, onOpenSwitcher, onSearch, onCollapse, }) {
|
|
25
|
+
return (_jsxs(XStack, { ...slot('sidebar-header'), items: "center", gap: "$1", px: "$1", py: "$1.5", children: [_jsxs(XStack, { ...ROW, items: "center", gap: "$1", shrink: 1, cursor: onOpenSwitcher ? 'pointer' : undefined, onPress: onOpenSwitcher, hoverStyle: onOpenSwitcher ? { bg: '$color4' } : undefined, pressStyle: onOpenSwitcher ? { bg: '$color5' } : undefined, children: [_jsx(SizableText, { size: "$3", fontWeight: "600", numberOfLines: 1, children: title }), onOpenSwitcher ? _jsx(ChevronDown, { size: 14, opacity: 0.6 }) : null] }), _jsx(XStack, { flex: 1 }), onSearch ? (_jsx(SidebarIconButton, { label: "Search conversations", onPress: onSearch, children: _jsx(Search, { size: 16 }) })) : null, onCollapse ? (_jsx(SidebarIconButton, { label: "Collapse sidebar", onPress: onCollapse, children: _jsx(PanelLeft, { size: 16 }) })) : null] }));
|
|
26
|
+
}
|
|
27
|
+
export function SidebarIconButton({ label, onPress, children }) {
|
|
28
|
+
return (_jsx(XStack, { width: 28, height: 28, items: "center", justify: "center", rounded: "$3", cursor: "pointer", opacity: 0.7, onPress: onPress, role: "button", tabIndex: 0, "aria-label": label, ...tip(label), hoverStyle: { bg: '$color4', opacity: 1 }, pressStyle: { bg: '$color5' }, children: children }));
|
|
29
|
+
}
|
|
30
|
+
export function SidebarNewChat({ label = 'New chat', onPress }) {
|
|
31
|
+
return (_jsxs(XStack, { ...slot('sidebar-new-chat'), ...ROW, items: "center", gap: "$2", cursor: "pointer", onPress: onPress, role: "button", tabIndex: 0, hoverStyle: { bg: '$color4' }, pressStyle: { bg: '$color5' }, children: [_jsx(SquarePen, { size: 16 }), _jsx(SizableText, { size: "$2", fontWeight: "500", children: label })] }));
|
|
32
|
+
}
|
|
33
|
+
/** SidebarScroll — the scrolling middle, so header and user chip stay pinned. */
|
|
34
|
+
export function SidebarScroll({ children }) {
|
|
35
|
+
return (_jsx(ScrollView, { ...slot('sidebar-scroll'), flex: 1, showsVerticalScrollIndicator: false, children: _jsx(YStack, { gap: "$0.5", children: children }) }));
|
|
36
|
+
}
|
|
37
|
+
export function SidebarSection({ label, children }) {
|
|
38
|
+
return (_jsxs(YStack, { ...slot('sidebar-section'), mt: "$3", gap: "$0.5", children: [label ? (_jsx(SizableText, { size: "$1", px: "$2", py: "$1", color: "$color10", fontWeight: "500", children: label })) : null, children] }));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* SidebarItem — one conversation.
|
|
42
|
+
*
|
|
43
|
+
* The title is clamped to a single line rather than wrapped: generated titles
|
|
44
|
+
* run long, and a wrapping row makes the list's scan height irregular while the
|
|
45
|
+
* first few words are what identify a conversation anyway.
|
|
46
|
+
*/
|
|
47
|
+
export function SidebarItem({ children, active = false, onPress, icon }) {
|
|
48
|
+
return (_jsxs(XStack, { ...slot('sidebar-item'), ...ROW, items: "center", gap: "$2", cursor: "pointer", onPress: onPress, role: "button", tabIndex: 0, "aria-current": active ? 'page' : undefined, bg: active ? '$color4' : undefined, hoverStyle: { bg: active ? '$color4' : '$color3' }, pressStyle: { bg: '$color5' }, children: [icon ? _jsx(YStack, { opacity: 0.7, children: icon }) : null, _jsx(SizableText, { size: "$2", numberOfLines: 1, flex: 1, color: active ? '$color' : '$color11', children: children })] }));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* SidebarFolder — a collapsible group.
|
|
52
|
+
*
|
|
53
|
+
* Uncontrolled by default and controlled the moment `open` is supplied, so the
|
|
54
|
+
* common case needs no state while a surface that persists expansion can still
|
|
55
|
+
* drive it.
|
|
56
|
+
*/
|
|
57
|
+
export function SidebarFolder({ name, children, defaultOpen = false, open: openProp, onOpenChange, }) {
|
|
58
|
+
const [own, setOwn] = useState(defaultOpen);
|
|
59
|
+
const controlled = openProp !== undefined;
|
|
60
|
+
const open = controlled ? openProp : own;
|
|
61
|
+
const toggle = () => {
|
|
62
|
+
if (!controlled)
|
|
63
|
+
setOwn((v) => !v);
|
|
64
|
+
onOpenChange?.(!open);
|
|
65
|
+
};
|
|
66
|
+
return (_jsxs(YStack, { ...slot('sidebar-folder'), children: [_jsxs(XStack, { ...ROW, items: "center", gap: "$1.5", cursor: "pointer", onPress: toggle, role: "button", tabIndex: 0, "aria-expanded": open, hoverStyle: { bg: '$color3' }, pressStyle: { bg: '$color5' }, children: [open ? (_jsx(ChevronDown, { size: 14, opacity: 0.6 })) : (_jsx(ChevronRight, { size: 14, opacity: 0.6 })), _jsx(Folder, { size: 16, opacity: 0.7 }), _jsx(SizableText, { size: "$2", numberOfLines: 1, flex: 1, color: "$color11", children: name })] }), open ? (_jsx(YStack, { pl: "$4", gap: "$0.5", children: children })) : null] }));
|
|
67
|
+
}
|
|
68
|
+
export function SidebarUser({ name, secondary, avatar, onPress, onHelp }) {
|
|
69
|
+
return (_jsxs(XStack, { ...slot('sidebar-user'), items: "center", gap: "$1", mt: "$1", pt: "$2", borderTopWidth: 1, borderColor: "$borderColor", children: [_jsxs(XStack, { ...ROW, items: "center", gap: "$2", flex: 1, cursor: "pointer", onPress: onPress, role: "button", tabIndex: 0, hoverStyle: { bg: '$color3' }, pressStyle: { bg: '$color5' }, children: [_jsx(XStack, { width: 24, height: 24, rounded: 9999, items: "center", justify: "center", bg: "$color5", overflow: "hidden", children: avatar ?? (_jsx(SizableText, { size: "$1", fontWeight: "600", children: name.charAt(0).toUpperCase() })) }), _jsxs(YStack, { flex: 1, children: [_jsx(SizableText, { size: "$2", numberOfLines: 1, children: name }), secondary ? (_jsx(SizableText, { size: "$1", color: "$color10", numberOfLines: 1, children: secondary })) : null] })] }), onHelp ? (_jsx(SidebarIconButton, { label: "Help", onPress: onHelp, children: _jsx(CircleHelp, { size: 16 }) })) : null] }));
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=Sidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../src/chat/Sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Sources = Sources;
|
|
5
|
+
exports.SourceChip = SourceChip;
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
/**
|
|
8
|
+
* Sources — the citation grid for a turn.
|
|
9
|
+
*
|
|
10
|
+
* A dense grid of marks rather than a list of titles. Sources are scanned for
|
|
11
|
+
* "which of these do I already trust", and twenty full-width titles would push
|
|
12
|
+
* the rail well past a screen. Each mark keeps its title as accessible name and
|
|
13
|
+
* tooltip, so the information is reordered, not discarded.
|
|
14
|
+
*/
|
|
15
|
+
const gui_1 = require("@hanzo/gui");
|
|
16
|
+
const slot_1 = require("../backends/gui/slot.cjs");
|
|
17
|
+
function Sources({ sources, title = 'Sources', onOpen }) {
|
|
18
|
+
if (sources.length === 0)
|
|
19
|
+
return null;
|
|
20
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('sources'), gap: "$2", p: "$3", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1.5", children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", fontWeight: "500", color: "$color10", children: title }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color9", children: sources.length })] }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flexWrap: "wrap", gap: "$1.5", children: sources.map((source) => ((0, jsx_runtime_1.jsx)(SourceChip, { source: source, onOpen: onOpen }, source.id))) })] }));
|
|
21
|
+
}
|
|
22
|
+
function SourceChip({ source, onOpen }) {
|
|
23
|
+
const press = onOpen ? () => onOpen(source) : undefined;
|
|
24
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('source-chip'), width: 28, height: 28, items: "center", justify: "center", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", bg: "$color3", overflow: "hidden", cursor: press ? 'pointer' : undefined, onPress: press, role: press ? 'button' : undefined, tabIndex: press ? 0 : undefined, "aria-label": source.title, ...(0, slot_1.tip)(source.title), hoverStyle: press ? { borderColor: '$color8' } : undefined, pressStyle: press ? { bg: '$color5' } : undefined, children: source.icon ?? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color11", children: source.title.charAt(0).toUpperCase() })) }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface Source {
|
|
3
|
+
id: string;
|
|
4
|
+
/** Accessible name and tooltip — a title, repo or file path. */
|
|
5
|
+
title: string;
|
|
6
|
+
/** Opened on press. Surfaces without navigation can omit it. */
|
|
7
|
+
href?: string;
|
|
8
|
+
/** Favicon or mark. Falls back to the first letter of `title`. */
|
|
9
|
+
icon?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export interface SourcesProps {
|
|
12
|
+
sources: Source[];
|
|
13
|
+
title?: string;
|
|
14
|
+
/** Raised on press. Given `href`, a surface may navigate instead. */
|
|
15
|
+
onOpen?: (source: Source) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function Sources({ sources, title, onOpen }: SourcesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
18
|
+
export interface SourceChipProps {
|
|
19
|
+
source: Source;
|
|
20
|
+
onOpen?: (source: Source) => void;
|
|
21
|
+
}
|
|
22
|
+
export declare function SourceChip({ source, onOpen }: SourceChipProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=Sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sources.d.ts","sourceRoot":"","sources":["../../src/chat/Sources.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kEAAkE;IAClE,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qEAAqE;IACrE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAED,wBAAgB,OAAO,CAAC,EAAE,OAAO,EAAE,KAAiB,EAAE,MAAM,EAAE,EAAE,YAAY,kDAqB3E;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAED,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,eAAe,2CA+B7D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Sources — the citation grid for a turn.
|
|
5
|
+
*
|
|
6
|
+
* A dense grid of marks rather than a list of titles. Sources are scanned for
|
|
7
|
+
* "which of these do I already trust", and twenty full-width titles would push
|
|
8
|
+
* the rail well past a screen. Each mark keeps its title as accessible name and
|
|
9
|
+
* tooltip, so the information is reordered, not discarded.
|
|
10
|
+
*/
|
|
11
|
+
import { SizableText, XStack, YStack } from '@hanzo/gui';
|
|
12
|
+
import { slot, tip } from '../backends/gui/slot.js';
|
|
13
|
+
export function Sources({ sources, title = 'Sources', onOpen }) {
|
|
14
|
+
if (sources.length === 0)
|
|
15
|
+
return null;
|
|
16
|
+
return (_jsxs(YStack, { ...slot('sources'), gap: "$2", p: "$3", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", children: [_jsxs(XStack, { items: "center", gap: "$1.5", children: [_jsx(SizableText, { size: "$1", fontWeight: "500", color: "$color10", children: title }), _jsx(SizableText, { size: "$1", color: "$color9", children: sources.length })] }), _jsx(XStack, { flexWrap: "wrap", gap: "$1.5", children: sources.map((source) => (_jsx(SourceChip, { source: source, onOpen: onOpen }, source.id))) })] }));
|
|
17
|
+
}
|
|
18
|
+
export function SourceChip({ source, onOpen }) {
|
|
19
|
+
const press = onOpen ? () => onOpen(source) : undefined;
|
|
20
|
+
return (_jsx(XStack, { ...slot('source-chip'), width: 28, height: 28, items: "center", justify: "center", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", bg: "$color3", overflow: "hidden", cursor: press ? 'pointer' : undefined, onPress: press, role: press ? 'button' : undefined, tabIndex: press ? 0 : undefined, "aria-label": source.title, ...tip(source.title), hoverStyle: press ? { borderColor: '$color8' } : undefined, pressStyle: press ? { bg: '$color5' } : undefined, children: source.icon ?? (_jsx(SizableText, { size: "$1", color: "$color11", children: source.title.charAt(0).toUpperCase() })) }));
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=Sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sources.js","sourceRoot":"","sources":["../../src/chat/Sources.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGxD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAmBhD,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,GAAG,SAAS,EAAE,MAAM,EAAgB;IAC1E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAErC,OAAO,CACL,MAAC,MAAM,OAAK,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAC,IAAI,EAAC,CAAC,EAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,WAAW,EAAE,CAAC,EAAE,WAAW,EAAC,cAAc,aAClG,MAAC,MAAM,IAAC,KAAK,EAAC,QAAQ,EAAC,GAAG,EAAC,MAAM,aAC/B,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,UAAU,EAAC,KAAK,EAAC,KAAK,EAAC,UAAU,YACrD,KAAK,GACM,EACd,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,SAAS,YACnC,OAAO,CAAC,MAAM,GACH,IACP,EAET,KAAC,MAAM,IAAC,QAAQ,EAAC,MAAM,EAAC,GAAG,EAAC,MAAM,YAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,KAAC,UAAU,IAAiB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,IAAzC,MAAM,CAAC,EAAE,CAAoC,CAC/D,CAAC,GACK,IACF,CACV,CAAA;AACH,CAAC;AAOD,MAAM,UAAU,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAmB;IAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAEvD,OAAO,CACL,KAAC,MAAM,OACD,IAAI,CAAC,aAAa,CAAC,EACvB,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,KAAK,EAAC,QAAQ,EACd,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,EAAE,EAAC,SAAS,EACZ,QAAQ,EAAC,QAAQ,EACjB,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EACrC,OAAO,EAAE,KAAK,EACd,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAClC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,gBACnB,MAAM,CAAC,KAAK,KACpB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EACrB,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,EAC1D,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,YAEhD,MAAM,CAAC,IAAI,IAAI,CACd,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,UAAU,YACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GACzB,CACf,GACM,CACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Thread = Thread;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
/**
|
|
7
|
+
* Thread — the scrolling column of turns.
|
|
8
|
+
*
|
|
9
|
+
* It does the one thing every surface had re-solved: follow a streaming answer
|
|
10
|
+
* to the bottom, and stop following the instant the reader scrolls up. The
|
|
11
|
+
* decision is `pinned()`, asserted without a DOM; this component only wires it
|
|
12
|
+
* to the platform's scroll view, so momentum and keyboard stay the host's.
|
|
13
|
+
*/
|
|
14
|
+
const gui_1 = require("@hanzo/gui");
|
|
15
|
+
const react_1 = require("react");
|
|
16
|
+
const slot_1 = require("../backends/gui/slot.cjs");
|
|
17
|
+
const stick_1 = require("./stick.cjs");
|
|
18
|
+
/** Reading-measure cap for prose, in px. */
|
|
19
|
+
const MEASURE = 768;
|
|
20
|
+
function Thread({ children, maxWidth = MEASURE, slack = stick_1.SLACK, gap = 24 }) {
|
|
21
|
+
const view = (0, react_1.useRef)(null);
|
|
22
|
+
const track = (0, react_1.useRef)({ offset: 0, viewport: 0, content: 0 });
|
|
23
|
+
const follow = (0, react_1.useRef)(true);
|
|
24
|
+
const grew = (0, react_1.useCallback)(() => {
|
|
25
|
+
if (follow.current)
|
|
26
|
+
view.current?.scrollToEnd({ animated: false });
|
|
27
|
+
}, []);
|
|
28
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.ScrollView, { ref: view, ...(0, slot_1.slot)('thread'), flex: 1, width: "100%", scrollEventThrottle: 16, onLayout: (e) => {
|
|
29
|
+
track.current = { ...track.current, viewport: e.nativeEvent.layout.height };
|
|
30
|
+
}, onContentSizeChange: (_w, h) => {
|
|
31
|
+
track.current = { ...track.current, content: h };
|
|
32
|
+
grew();
|
|
33
|
+
}, onScroll: (e) => {
|
|
34
|
+
const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent;
|
|
35
|
+
track.current = {
|
|
36
|
+
offset: contentOffset.y,
|
|
37
|
+
viewport: layoutMeasurement.height,
|
|
38
|
+
content: contentSize.height,
|
|
39
|
+
};
|
|
40
|
+
follow.current = (0, stick_1.pinned)(track.current, slack);
|
|
41
|
+
}, children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('thread-column'), width: "100%", gap: gap, py: gap, ...(maxWidth ? { maxW: maxWidth, self: 'center', px: '$3' } : null), children: children }) }));
|
|
42
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export interface ThreadProps {
|
|
3
|
+
children?: ReactNode;
|
|
4
|
+
/** Reading-measure cap. Pass `0` to fill the container. */
|
|
5
|
+
maxWidth?: number;
|
|
6
|
+
/** How near the end still counts as "at the bottom", in px. */
|
|
7
|
+
slack?: number;
|
|
8
|
+
gap?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function Thread({ children, maxWidth, slack, gap }: ThreadProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=Thread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Thread.d.ts","sourceRoot":"","sources":["../../src/chat/Thread.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAQ3D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAkB,EAAE,KAAa,EAAE,GAAQ,EAAE,EAAE,WAAW,2CA4C5F"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Thread — the scrolling column of turns.
|
|
5
|
+
*
|
|
6
|
+
* It does the one thing every surface had re-solved: follow a streaming answer
|
|
7
|
+
* to the bottom, and stop following the instant the reader scrolls up. The
|
|
8
|
+
* decision is `pinned()`, asserted without a DOM; this component only wires it
|
|
9
|
+
* to the platform's scroll view, so momentum and keyboard stay the host's.
|
|
10
|
+
*/
|
|
11
|
+
import { ScrollView, YStack } from '@hanzo/gui';
|
|
12
|
+
import { useCallback, useRef } from 'react';
|
|
13
|
+
import { slot } from '../backends/gui/slot.js';
|
|
14
|
+
import { pinned, SLACK } from './stick.js';
|
|
15
|
+
/** Reading-measure cap for prose, in px. */
|
|
16
|
+
const MEASURE = 768;
|
|
17
|
+
export function Thread({ children, maxWidth = MEASURE, slack = SLACK, gap = 24 }) {
|
|
18
|
+
const view = useRef(null);
|
|
19
|
+
const track = useRef({ offset: 0, viewport: 0, content: 0 });
|
|
20
|
+
const follow = useRef(true);
|
|
21
|
+
const grew = useCallback(() => {
|
|
22
|
+
if (follow.current)
|
|
23
|
+
view.current?.scrollToEnd({ animated: false });
|
|
24
|
+
}, []);
|
|
25
|
+
return (_jsx(ScrollView, { ref: view, ...slot('thread'), flex: 1, width: "100%", scrollEventThrottle: 16, onLayout: (e) => {
|
|
26
|
+
track.current = { ...track.current, viewport: e.nativeEvent.layout.height };
|
|
27
|
+
}, onContentSizeChange: (_w, h) => {
|
|
28
|
+
track.current = { ...track.current, content: h };
|
|
29
|
+
grew();
|
|
30
|
+
}, onScroll: (e) => {
|
|
31
|
+
const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent;
|
|
32
|
+
track.current = {
|
|
33
|
+
offset: contentOffset.y,
|
|
34
|
+
viewport: layoutMeasurement.height,
|
|
35
|
+
content: contentSize.height,
|
|
36
|
+
};
|
|
37
|
+
follow.current = pinned(track.current, slack);
|
|
38
|
+
}, children: _jsx(YStack, { ...slot('thread-column'), width: "100%", gap: gap, py: gap, ...(maxWidth ? { maxW: maxWidth, self: 'center', px: '$3' } : null), children: children }) }));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=Thread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Thread.js","sourceRoot":"","sources":["../../src/chat/Thread.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAe,MAAM,YAAY,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAA;AAE3D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,4CAA4C;AAC5C,MAAM,OAAO,GAAG,GAAG,CAAA;AAWnB,MAAM,UAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,GAAG,EAAE,EAAe;IAC3F,MAAM,IAAI,GAAG,MAAM,CAA4B,IAAI,CAAC,CAAA;IACpD,MAAM,KAAK,GAAG,MAAM,CAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;IACnE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IAE3B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,IAAI,MAAM,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;IACpE,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,KAAC,UAAU,IACT,GAAG,EAAE,IAAI,KACL,IAAI,CAAC,QAAQ,CAAC,EAClB,IAAI,EAAE,CAAC,EACP,KAAK,EAAC,MAAM,EACZ,mBAAmB,EAAE,EAAE,EACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;YACd,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;QAC7E,CAAC,EACD,mBAAmB,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;YAC7B,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;YAChD,IAAI,EAAE,CAAA;QACR,CAAC,EACD,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;YACd,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,WAAW,CAAA;YACvE,KAAK,CAAC,OAAO,GAAG;gBACd,MAAM,EAAE,aAAa,CAAC,CAAC;gBACvB,QAAQ,EAAE,iBAAiB,CAAC,MAAM;gBAClC,OAAO,EAAE,WAAW,CAAC,MAAM;aAC5B,CAAA;YACD,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC/C,CAAC,YAED,KAAC,MAAM,OACD,IAAI,CAAC,eAAe,CAAC,EACzB,KAAK,EAAC,MAAM,EACZ,GAAG,EAAE,GAAG,EACR,EAAE,EAAE,GAAG,KACH,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAE5E,QAAQ,GACF,GACE,CACd,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SourceChip = exports.Sources = exports.CopyButton = exports.Code = exports.Aside = exports.AsideToggle = exports.ShareButton = exports.HeaderButton = exports.Header = exports.SidebarUser = exports.SidebarFolder = exports.SidebarItem = exports.SidebarSection = exports.SidebarScroll = exports.SidebarNewChat = exports.SidebarIconButton = exports.SidebarHeader = exports.Sidebar = exports.SLACK = exports.pinned = exports.sends = exports.ready = exports.Thread = exports.Message = exports.ASK = exports.Composer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @hanzo/ui/chat — the one chat shell, on @hanzo/gui primitives.
|
|
6
|
+
*
|
|
7
|
+
* Shell only: Thread scrolls, Message presents a turn, Composer takes a draft,
|
|
8
|
+
* Sidebar navigates between conversations, Header names the current one, Code
|
|
9
|
+
* and Sources present the two pieces of a turn every surface renders the same
|
|
10
|
+
* way. Content rendering (markdown, tool calls) stays with the surface — they
|
|
11
|
+
* disagree on the pipeline, and none of it is presentational.
|
|
12
|
+
*
|
|
13
|
+
* Everything is props-in, callbacks-out: no transport, no store, no routing, no
|
|
14
|
+
* active-id resolution. The same components serve a live conversation, a shared
|
|
15
|
+
* read-only transcript and a test fixture.
|
|
16
|
+
*
|
|
17
|
+
* Styling is `$` tokens throughout, never literal colours, so each brand retunes
|
|
18
|
+
* through its own theme and nothing here carries a Hanzo mark — which is what
|
|
19
|
+
* lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
|
|
20
|
+
*
|
|
21
|
+
* The model picker is not here: it already ships at `@hanzo/ui/models`, and it
|
|
22
|
+
* is not chat-specific.
|
|
23
|
+
*/
|
|
24
|
+
var Composer_1 = require("./Composer.cjs");
|
|
25
|
+
Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return Composer_1.Composer; } });
|
|
26
|
+
Object.defineProperty(exports, "ASK", { enumerable: true, get: function () { return Composer_1.ASK; } });
|
|
27
|
+
var Message_1 = require("./Message.cjs");
|
|
28
|
+
Object.defineProperty(exports, "Message", { enumerable: true, get: function () { return Message_1.Message; } });
|
|
29
|
+
var Thread_1 = require("./Thread.cjs");
|
|
30
|
+
Object.defineProperty(exports, "Thread", { enumerable: true, get: function () { return Thread_1.Thread; } });
|
|
31
|
+
var send_1 = require("./send.cjs");
|
|
32
|
+
Object.defineProperty(exports, "ready", { enumerable: true, get: function () { return send_1.ready; } });
|
|
33
|
+
Object.defineProperty(exports, "sends", { enumerable: true, get: function () { return send_1.sends; } });
|
|
34
|
+
var stick_1 = require("./stick.cjs");
|
|
35
|
+
Object.defineProperty(exports, "pinned", { enumerable: true, get: function () { return stick_1.pinned; } });
|
|
36
|
+
Object.defineProperty(exports, "SLACK", { enumerable: true, get: function () { return stick_1.SLACK; } });
|
|
37
|
+
var Sidebar_1 = require("./Sidebar.cjs");
|
|
38
|
+
Object.defineProperty(exports, "Sidebar", { enumerable: true, get: function () { return Sidebar_1.Sidebar; } });
|
|
39
|
+
Object.defineProperty(exports, "SidebarHeader", { enumerable: true, get: function () { return Sidebar_1.SidebarHeader; } });
|
|
40
|
+
Object.defineProperty(exports, "SidebarIconButton", { enumerable: true, get: function () { return Sidebar_1.SidebarIconButton; } });
|
|
41
|
+
Object.defineProperty(exports, "SidebarNewChat", { enumerable: true, get: function () { return Sidebar_1.SidebarNewChat; } });
|
|
42
|
+
Object.defineProperty(exports, "SidebarScroll", { enumerable: true, get: function () { return Sidebar_1.SidebarScroll; } });
|
|
43
|
+
Object.defineProperty(exports, "SidebarSection", { enumerable: true, get: function () { return Sidebar_1.SidebarSection; } });
|
|
44
|
+
Object.defineProperty(exports, "SidebarItem", { enumerable: true, get: function () { return Sidebar_1.SidebarItem; } });
|
|
45
|
+
Object.defineProperty(exports, "SidebarFolder", { enumerable: true, get: function () { return Sidebar_1.SidebarFolder; } });
|
|
46
|
+
Object.defineProperty(exports, "SidebarUser", { enumerable: true, get: function () { return Sidebar_1.SidebarUser; } });
|
|
47
|
+
var Header_1 = require("./Header.cjs");
|
|
48
|
+
Object.defineProperty(exports, "Header", { enumerable: true, get: function () { return Header_1.Header; } });
|
|
49
|
+
Object.defineProperty(exports, "HeaderButton", { enumerable: true, get: function () { return Header_1.HeaderButton; } });
|
|
50
|
+
Object.defineProperty(exports, "ShareButton", { enumerable: true, get: function () { return Header_1.ShareButton; } });
|
|
51
|
+
Object.defineProperty(exports, "AsideToggle", { enumerable: true, get: function () { return Header_1.AsideToggle; } });
|
|
52
|
+
Object.defineProperty(exports, "Aside", { enumerable: true, get: function () { return Header_1.Aside; } });
|
|
53
|
+
var Code_1 = require("./Code.cjs");
|
|
54
|
+
Object.defineProperty(exports, "Code", { enumerable: true, get: function () { return Code_1.Code; } });
|
|
55
|
+
Object.defineProperty(exports, "CopyButton", { enumerable: true, get: function () { return Code_1.CopyButton; } });
|
|
56
|
+
var Sources_1 = require("./Sources.cjs");
|
|
57
|
+
Object.defineProperty(exports, "Sources", { enumerable: true, get: function () { return Sources_1.Sources; } });
|
|
58
|
+
Object.defineProperty(exports, "SourceChip", { enumerable: true, get: function () { return Sources_1.SourceChip; } });
|