@hanzo/ui 8.0.28 → 8.0.32
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/button.d.ts +12 -0
- package/dist/backends/gui/button.d.ts.map +1 -1
- package/dist/backends/gui/button.js.map +1 -1
- 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,43 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Header — the conversation title bar.
|
|
5
|
+
*
|
|
6
|
+
* Title on the left, `children` as the action slot on the right. The actions are
|
|
7
|
+
* a slot rather than a fixed set because what belongs there is per-surface:
|
|
8
|
+
* hanzo.chat shares and opens a details rail, the console shows the owning
|
|
9
|
+
* project, hanzo.app shows neither.
|
|
10
|
+
*/
|
|
11
|
+
import { SizableText, XStack, YStack } from '@hanzo/gui';
|
|
12
|
+
import { Ellipsis, PanelRight, Share2 } from '@hanzogui/lucide-icons-2';
|
|
13
|
+
import { slot, tip } from '../backends/gui/slot.js';
|
|
14
|
+
export function Header({ title, onOpenMenu, children }) {
|
|
15
|
+
return (_jsxs(XStack, { ...slot('chat-header'), width: "100%", height: 48, shrink: 0, items: "center", gap: "$2", px: "$3", borderBottomWidth: 1, borderColor: "$borderColor", bg: "$background", children: [_jsxs(XStack, { items: "center", gap: "$1", shrink: 1, children: [_jsx(SizableText, { size: "$2", fontWeight: "500", numberOfLines: 1, children: title }), onOpenMenu ? (_jsx(HeaderButton, { label: "Conversation options", onPress: onOpenMenu, children: _jsx(Ellipsis, { size: 16 }) })) : null] }), _jsx(XStack, { flex: 1 }), children] }));
|
|
16
|
+
}
|
|
17
|
+
export function HeaderButton({ label, onPress, children }) {
|
|
18
|
+
return (_jsx(XStack, { width: 32, height: 32, 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 }));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* ShareButton — carries a word, unlike its neighbours.
|
|
22
|
+
*
|
|
23
|
+
* Sharing sends the conversation somewhere else and is not quietly undoable, so
|
|
24
|
+
* it reads as a label rather than a glyph. Everything reversible in this bar is
|
|
25
|
+
* an icon; this deliberately is not.
|
|
26
|
+
*/
|
|
27
|
+
export function ShareButton({ label = 'Share', onPress }) {
|
|
28
|
+
return (_jsxs(XStack, { ...slot('chat-share'), items: "center", gap: "$1.5", px: "$2.5", py: "$1.5", rounded: "$3", cursor: "pointer", opacity: 0.8, onPress: onPress, role: "button", tabIndex: 0, hoverStyle: { bg: '$color4', opacity: 1 }, pressStyle: { bg: '$color5' }, children: [_jsx(Share2, { size: 14 }), _jsx(SizableText, { size: "$1", fontWeight: "500", children: label })] }));
|
|
29
|
+
}
|
|
30
|
+
export function AsideToggle({ label = 'Toggle details panel', onPress }) {
|
|
31
|
+
return (_jsx(HeaderButton, { label: label, onPress: onPress, children: _jsx(PanelRight, { size: 16 }) }));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Aside — the right rail (sources, artifacts, run details).
|
|
35
|
+
*
|
|
36
|
+
* Its own column, not an overlay: an overlay would sit on top of the prose the
|
|
37
|
+
* reader is comparing it against, which is the one thing a citation panel must
|
|
38
|
+
* not do. Surfaces hide it at narrow widths by not rendering it.
|
|
39
|
+
*/
|
|
40
|
+
export function Aside({ children, width = 320 }) {
|
|
41
|
+
return (_jsx(YStack, { ...slot('chat-aside'), width: width, shrink: 0, height: "100%", p: "$3", gap: "$3", borderLeftWidth: 1, borderColor: "$borderColor", children: children }));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=Header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/chat/Header.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAGvE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAUhD,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAe;IACjE,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,aAAa,CAAC,EACvB,KAAK,EAAC,MAAM,EACZ,MAAM,EAAE,EAAE,EACV,MAAM,EAAE,CAAC,EACT,KAAK,EAAC,QAAQ,EACd,GAAG,EAAC,IAAI,EACR,EAAE,EAAC,IAAI,EACP,iBAAiB,EAAE,CAAC,EACpB,WAAW,EAAC,cAAc,EAC1B,EAAE,EAAC,aAAa,aAEhB,MAAC,MAAM,IAAC,KAAK,EAAC,QAAQ,EAAC,GAAG,EAAC,IAAI,EAAC,MAAM,EAAE,CAAC,aAKvC,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,UAAU,EAAC,KAAK,EAAC,aAAa,EAAE,CAAC,YACrD,KAAK,GACM,EACb,UAAU,CAAC,CAAC,CAAC,CACZ,KAAC,YAAY,IAAC,KAAK,EAAC,sBAAsB,EAAC,OAAO,EAAE,UAAU,YAC5D,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,GAAI,GACT,CAChB,CAAC,CAAC,CAAC,IAAI,IACD,EAET,KAAC,MAAM,IAAC,IAAI,EAAE,CAAC,GAAI,EAClB,QAAQ,IACF,CACV,CAAA;AACH,CAAC;AASD,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAqB;IAC1E,OAAO,CACL,KAAC,MAAM,IACL,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,KAAK,EAAC,QAAQ,EACd,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,IAAI,EACZ,MAAM,EAAC,SAAS,EAChB,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,OAAO,EAChB,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,gBACC,KAAK,KACb,GAAG,CAAC,KAAK,CAAC,EACd,UAAU,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,EACzC,UAAU,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,YAE5B,QAAQ,GACF,CACV,CAAA;AACH,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,GAAG,OAAO,EAAE,OAAO,EAAoB;IACxE,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,YAAY,CAAC,EACtB,KAAK,EAAC,QAAQ,EACd,GAAG,EAAC,MAAM,EACV,EAAE,EAAC,MAAM,EACT,EAAE,EAAC,MAAM,EACT,OAAO,EAAC,IAAI,EACZ,MAAM,EAAC,SAAS,EAChB,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,OAAO,EAChB,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,EACX,UAAU,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,EACzC,UAAU,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,aAE7B,KAAC,MAAM,IAAC,IAAI,EAAE,EAAE,GAAI,EACpB,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,UAAU,EAAC,KAAK,YACpC,KAAK,GACM,IACP,CACV,CAAA;AACH,CAAC;AAOD,MAAM,UAAU,WAAW,CAAC,EAAE,KAAK,GAAG,sBAAsB,EAAE,OAAO,EAAoB;IACvF,OAAO,CACL,KAAC,YAAY,IAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,YAC1C,KAAC,UAAU,IAAC,IAAI,EAAE,EAAE,GAAI,GACX,CAChB,CAAA;AACH,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,GAAG,GAAG,EAAc;IACzD,OAAO,CACL,KAAC,MAAM,OACD,IAAI,CAAC,YAAY,CAAC,EACtB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,CAAC,EACT,MAAM,EAAC,MAAM,EACb,CAAC,EAAC,IAAI,EACN,GAAG,EAAC,IAAI,EACR,eAAe,EAAE,CAAC,EAClB,WAAW,EAAC,cAAc,YAEzB,QAAQ,GACF,CACV,CAAA;AACH,CAAC"}
|
|
@@ -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"}
|