@hanzo/ui 8.1.3 → 8.1.5
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/textarea.cjs +35 -3
- package/dist/backends/gui/textarea.d.ts +34 -5
- package/dist/backends/gui/textarea.d.ts.map +1 -1
- package/dist/backends/gui/textarea.js +35 -3
- package/dist/backends/gui/textarea.js.map +1 -1
- package/dist/chat/Code.cjs +2 -2
- package/dist/chat/Code.d.ts +16 -3
- package/dist/chat/Code.d.ts.map +1 -1
- package/dist/chat/Code.js +2 -2
- package/dist/chat/Code.js.map +1 -1
- package/dist/chat/Composer.cjs +16 -10
- package/dist/chat/Composer.d.ts +59 -3
- package/dist/chat/Composer.d.ts.map +1 -1
- package/dist/chat/Composer.js +16 -10
- package/dist/chat/Composer.js.map +1 -1
- package/dist/chat/Failure.cjs +2 -2
- package/dist/chat/Failure.d.ts +29 -3
- package/dist/chat/Failure.d.ts.map +1 -1
- package/dist/chat/Failure.js +2 -2
- package/dist/chat/Failure.js.map +1 -1
- package/dist/chat/Header.cjs +2 -2
- package/dist/chat/Header.d.ts +20 -3
- package/dist/chat/Header.d.ts.map +1 -1
- package/dist/chat/Header.js +2 -2
- package/dist/chat/Header.js.map +1 -1
- package/dist/chat/Message.cjs +10 -4
- package/dist/chat/Message.d.ts +42 -3
- package/dist/chat/Message.d.ts.map +1 -1
- package/dist/chat/Message.js +10 -4
- package/dist/chat/Message.js.map +1 -1
- package/dist/chat/Sources.cjs +33 -10
- package/dist/chat/Sources.d.ts +46 -6
- package/dist/chat/Sources.d.ts.map +1 -1
- package/dist/chat/Sources.js +32 -9
- package/dist/chat/Sources.js.map +1 -1
- package/dist/chat/Step.cjs +2 -2
- package/dist/chat/Step.d.ts +4 -3
- package/dist/chat/Step.d.ts.map +1 -1
- package/dist/chat/Step.js +2 -2
- package/dist/chat/Step.js.map +1 -1
- package/dist/chat/Thread.cjs +38 -13
- package/dist/chat/Thread.d.ts +55 -3
- package/dist/chat/Thread.d.ts.map +1 -1
- package/dist/chat/Thread.js +38 -13
- package/dist/chat/Thread.js.map +1 -1
- package/dist/chat/index.cjs +19 -2
- package/dist/chat/index.d.ts +18 -1
- package/dist/chat/index.d.ts.map +1 -1
- package/dist/chat/index.js +18 -1
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/pure.cjs +41 -0
- package/dist/chat/pure.d.ts +3 -0
- package/dist/chat/pure.d.ts.map +1 -0
- package/dist/chat/pure.js +35 -0
- package/dist/chat/pure.js.map +1 -0
- package/dist/chat/send.cjs +10 -1
- package/dist/chat/send.d.ts +9 -0
- package/dist/chat/send.d.ts.map +1 -1
- package/dist/chat/send.js +10 -1
- package/dist/chat/send.js.map +1 -1
- package/dist/chat/stick.cjs +1 -1
- package/dist/chat/stick.js +1 -1
- package/dist/gallery.cjs +5 -4
- package/dist/gallery.d.ts.map +1 -1
- package/dist/gallery.js +5 -4
- package/dist/gallery.js.map +1 -1
- package/dist/product/CopyButton.cjs +2 -2
- package/dist/product/CopyButton.d.ts +12 -2
- package/dist/product/CopyButton.d.ts.map +1 -1
- package/dist/product/CopyButton.js +2 -2
- package/dist/product/CopyButton.js.map +1 -1
- package/dist/product/pure.cjs +12 -1
- package/dist/product/pure.d.ts +2 -0
- package/dist/product/pure.d.ts.map +1 -1
- package/dist/product/pure.js +7 -0
- package/dist/product/pure.js.map +1 -1
- package/dist/styles.css +14 -2
- package/package.json +7 -1
package/dist/chat/Header.js
CHANGED
|
@@ -11,8 +11,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
import { SizableText, XStack, YStack } from '@hanzo/gui';
|
|
12
12
|
import { Ellipsis, PanelRight, Share2 } from '@hanzogui/lucide-icons-2';
|
|
13
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] }));
|
|
14
|
+
export function Header({ title, onOpenMenu, children, leading, ...props }) {
|
|
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", ...props, children: [leading, _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
16
|
}
|
|
17
17
|
export function HeaderButton({ label, onPress, children }) {
|
|
18
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 }));
|
package/dist/chat/Header.js.map
CHANGED
|
@@ -1 +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;
|
|
1
|
+
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../src/chat/Header.tsx"],"names":[],"mappings":"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"}
|
package/dist/chat/Message.cjs
CHANGED
|
@@ -43,11 +43,17 @@ const slot_1 = require("../backends/gui/slot.cjs");
|
|
|
43
43
|
function Caret() {
|
|
44
44
|
return (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('caret'), width: 2, height: 15, rounded: 1, bg: "$color12", "aria-hidden": true });
|
|
45
45
|
}
|
|
46
|
-
function Message({ role, children, actions, busy = false, icon }) {
|
|
46
|
+
function Message({ role, children, actions, busy = false, icon, body, ...props }) {
|
|
47
47
|
if (role === 'system')
|
|
48
|
-
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 }) }));
|
|
48
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('message'), "data-role": "system", width: "100%", justify: "center", py: "$2", ...props, children: (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", text: "center", children: children }) }));
|
|
49
49
|
const mine = role === 'user';
|
|
50
|
-
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",
|
|
50
|
+
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",
|
|
51
|
+
// The row is a hover group, so an action strip can be revealed with
|
|
52
|
+
// `$group-hover` instead of by a wrapper each surface adds itself. Both
|
|
53
|
+
// hanzo/chat and hanzo.app reveal theirs on hover and both had to supply
|
|
54
|
+
// the group. Unnamed on purpose: gui types `group` as a BOOLEAN here, so
|
|
55
|
+
// `group="turn"` type-errors rather than registering a named group.
|
|
56
|
+
group: true, ...props, 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",
|
|
51
57
|
// 85%, because that is the number three independent implementations
|
|
52
58
|
// reached: hanzo/chat's `USER_TURN` (`common/turn.ts:17`,
|
|
53
59
|
// `max-w-[85%]`), hanzo.app `/chat` (`app/chat/page.tsx:521`,
|
|
@@ -59,5 +65,5 @@ function Message({ role, children, actions, busy = false, icon }) {
|
|
|
59
65
|
rounded: '$5',
|
|
60
66
|
px: '$3',
|
|
61
67
|
py: '$2',
|
|
62
|
-
}), children: [(0, ink_1.ink)(children), busy ? (0, jsx_runtime_1.jsx)(Caret, {}) : null, actions ? (0, jsx_runtime_1.jsx)(gui_1.XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
68
|
+
}), ...body, children: [(0, ink_1.ink)(children), busy ? (0, jsx_runtime_1.jsx)(Caret, {}) : null, actions ? (0, jsx_runtime_1.jsx)(gui_1.XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
63
69
|
}
|
package/dist/chat/Message.d.ts
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Message — one turn in a thread.
|
|
3
|
+
*
|
|
4
|
+
* Role drives presentation and nothing else: a user turn is a contained bubble
|
|
5
|
+
* that shrinks to its content, an assistant turn is full-bleed prose, a system
|
|
6
|
+
* turn is a muted aside. Content is `children`, so the surface keeps its own
|
|
7
|
+
* markdown pipeline — the surfaces disagree on remark plugins and none of that
|
|
8
|
+
* belongs in a presentational package.
|
|
9
|
+
*
|
|
10
|
+
* That arrangement is not this package's taste; it is what all six turn
|
|
11
|
+
* renderers across the estate independently arrived at. hanzo/chat states it
|
|
12
|
+
* outright in `client/src/components/Chat/Messages/ui/MessageRender.tsx:131`:
|
|
13
|
+
* "the user's turn is a glass bubble on the right, the reply plain and full
|
|
14
|
+
* width — the contrast is what says who is speaking." No avatar, no sender
|
|
15
|
+
* name, no timestamp — which is why `icon` is opt-in and there is no `name`
|
|
16
|
+
* prop. Only the read-only share view renders a name, and only one surface
|
|
17
|
+
* renders a timestamp.
|
|
18
|
+
*/
|
|
19
|
+
import { XStack } from '@hanzo/gui';
|
|
20
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
21
|
export type Role = 'user' | 'assistant' | 'system';
|
|
22
|
+
/**
|
|
23
|
+
* What a gui stack accepts — id, className, style, the `$` style props.
|
|
24
|
+
*
|
|
25
|
+
* `role` is dropped because this component already has one and means something
|
|
26
|
+
* else by it: the ARIA role of the row is not the speaker of the turn. The row
|
|
27
|
+
* needs no ARIA role, and `aria-label` is still reachable for the name.
|
|
28
|
+
*/
|
|
29
|
+
type Stack = Omit<ComponentProps<typeof XStack>, 'children' | 'role'>;
|
|
3
30
|
/**
|
|
4
31
|
* The mark that says a turn is still arriving.
|
|
5
32
|
*
|
|
@@ -16,7 +43,7 @@ export type Role = 'user' | 'assistant' | 'system';
|
|
|
16
43
|
* noise on every token.
|
|
17
44
|
*/
|
|
18
45
|
export declare function Caret(): import("react/jsx-runtime").JSX.Element;
|
|
19
|
-
export interface MessageProps {
|
|
46
|
+
export interface MessageProps extends Stack {
|
|
20
47
|
role: Role;
|
|
21
48
|
children?: ReactNode;
|
|
22
49
|
/** Row rendered under the turn — copy, retry, feedback. */
|
|
@@ -25,6 +52,18 @@ export interface MessageProps {
|
|
|
25
52
|
busy?: boolean;
|
|
26
53
|
/** Leading affordance for an assistant turn: avatar or model mark. */
|
|
27
54
|
icon?: ReactNode;
|
|
55
|
+
/**
|
|
56
|
+
* The bubble's own props — the inner box, not the row.
|
|
57
|
+
*
|
|
58
|
+
* The same reason `DialogContent` grew `overlay`: this component owns the
|
|
59
|
+
* body so a caller never has to assemble one, but owning is not hiding, and
|
|
60
|
+
* with nothing through, the fill, the corner and the width cap were
|
|
61
|
+
* unreachable from outside the package. hanzo/chat's turn is `glass hz-turn`
|
|
62
|
+
* with a `color-mix` fill it applies fleet-wide (`style.css:389`); it cannot
|
|
63
|
+
* adopt a bubble welded to `$color3`. Absent, nothing changes.
|
|
64
|
+
*/
|
|
65
|
+
body?: Stack;
|
|
28
66
|
}
|
|
29
|
-
export declare function Message({ role, children, actions, busy, icon }: MessageProps): import("react/jsx-runtime").JSX.Element;
|
|
67
|
+
export declare function Message({ role, children, actions, busy, icon, body, ...props }: MessageProps): import("react/jsx-runtime").JSX.Element;
|
|
68
|
+
export {};
|
|
30
69
|
//# sourceMappingURL=Message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAQ,MAAM,EAAU,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtD,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAA;AAElD;;;;;;GAMG;AACH,KAAK,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,CAAA;AAErE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,4CAEpB;AAED,MAAM,WAAW,YAAa,SAAQ,KAAK;IACzC,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,sEAAsE;IACtE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,KAAK,CAAA;CACb;AAED,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,IAAY,EACZ,IAAI,EACJ,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,YAAY,2CA4Dd"}
|
package/dist/chat/Message.js
CHANGED
|
@@ -39,11 +39,17 @@ import { slot } from '../backends/gui/slot.js';
|
|
|
39
39
|
export function Caret() {
|
|
40
40
|
return _jsx(YStack, { ...slot('caret'), width: 2, height: 15, rounded: 1, bg: "$color12", "aria-hidden": true });
|
|
41
41
|
}
|
|
42
|
-
export function Message({ role, children, actions, busy = false, icon }) {
|
|
42
|
+
export function Message({ role, children, actions, busy = false, icon, body, ...props }) {
|
|
43
43
|
if (role === 'system')
|
|
44
|
-
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 }) }));
|
|
44
|
+
return (_jsx(XStack, { ...slot('message'), "data-role": "system", width: "100%", justify: "center", py: "$2", ...props, children: _jsx(Text, { fontSize: "$1", color: "$color10", text: "center", children: children }) }));
|
|
45
45
|
const mine = role === 'user';
|
|
46
|
-
return (_jsxs(XStack, { ...slot('message'), "data-role": role, width: "100%", justify: mine ? 'flex-end' : 'flex-start', gap: "$2",
|
|
46
|
+
return (_jsxs(XStack, { ...slot('message'), "data-role": role, width: "100%", justify: mine ? 'flex-end' : 'flex-start', gap: "$2",
|
|
47
|
+
// The row is a hover group, so an action strip can be revealed with
|
|
48
|
+
// `$group-hover` instead of by a wrapper each surface adds itself. Both
|
|
49
|
+
// hanzo/chat and hanzo.app reveal theirs on hover and both had to supply
|
|
50
|
+
// the group. Unnamed on purpose: gui types `group` as a BOOLEAN here, so
|
|
51
|
+
// `group="turn"` type-errors rather than registering a named group.
|
|
52
|
+
group: true, ...props, children: [icon && !mine ? _jsx(YStack, { pt: "$1", children: icon }) : null, _jsxs(YStack, { ...slot('message-body'), "data-bubble": mine ? 'true' : undefined, gap: "$2",
|
|
47
53
|
// 85%, because that is the number three independent implementations
|
|
48
54
|
// reached: hanzo/chat's `USER_TURN` (`common/turn.ts:17`,
|
|
49
55
|
// `max-w-[85%]`), hanzo.app `/chat` (`app/chat/page.tsx:521`,
|
|
@@ -55,6 +61,6 @@ export function Message({ role, children, actions, busy = false, icon }) {
|
|
|
55
61
|
rounded: '$5',
|
|
56
62
|
px: '$3',
|
|
57
63
|
py: '$2',
|
|
58
|
-
}), children: [ink(children), busy ? _jsx(Caret, {}) : null, actions ? _jsx(XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
64
|
+
}), ...body, children: [ink(children), busy ? _jsx(Caret, {}) : null, actions ? _jsx(XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
59
65
|
}
|
|
60
66
|
//# sourceMappingURL=Message.js.map
|
package/dist/chat/Message.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.js","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"Message.js","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGjD,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAa3C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,KAAK;IACnB,OAAO,KAAC,MAAM,OAAK,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAC,UAAU,wBAAe,CAAA;AAClG,CAAC;AAwBD,MAAM,UAAU,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,IAAI,GAAG,KAAK,EACZ,IAAI,EACJ,IAAI,EACJ,GAAG,KAAK,EACK;IACb,IAAI,IAAI,KAAK,QAAQ;QACnB,OAAO,CACL,KAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,eACT,QAAQ,EAClB,KAAK,EAAC,MAAM,EACZ,OAAO,EAAC,QAAQ,EAChB,EAAE,EAAC,IAAI,KACH,KAAK,YAET,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;QACR,oEAAoE;QACpE,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,oEAAoE;QACpE,KAAK,WACD,KAAK,aAER,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;gBACR,oEAAoE;gBACpE,0DAA0D;gBAC1D,8DAA8D;gBAC9D,uDAAuD;gBACvD,mEAAmE;gBACnE,YAAY;gBACZ,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,KACE,IAAI,aAEP,GAAG,CAAC,QAAQ,CAAC,EACb,IAAI,CAAC,CAAC,CAAC,KAAC,KAAK,KAAG,CAAC,CAAC,CAAC,IAAI,EACvB,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"}
|
package/dist/chat/Sources.cjs
CHANGED
|
@@ -2,24 +2,47 @@
|
|
|
2
2
|
'use client';
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.Sources = Sources;
|
|
5
|
-
exports.
|
|
5
|
+
exports.SourceCard = SourceCard;
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
/**
|
|
8
|
-
* Sources — the
|
|
8
|
+
* Sources — the citations for a turn, as a strip of cards.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* This used to be a wrapping grid of 28px marks with the title reachable only
|
|
11
|
+
* as a tooltip, and the argument for it was density: sources are scanned for
|
|
12
|
+
* "which of these do I already trust", and twenty full-width titles push the
|
|
13
|
+
* rail past a screen. The density argument is right. Hiding the HOST was not,
|
|
14
|
+
* because the host is the answer to that exact question — a favicon is sixteen
|
|
15
|
+
* pixels of ambiguity and `nytimes.com` is a verdict — and neither surface that
|
|
16
|
+
* ships citations hides it. hanzo/chat's `SourceItem` (`components/Web/
|
|
17
|
+
* Sources.tsx`) draws favicon, domain, title and a snippet; the extension's
|
|
18
|
+
* `answer/Source.tsx:9-26` draws a number, a favicon, the host and a
|
|
19
|
+
* three-line-clamped title, and its own comment records where that came from:
|
|
20
|
+
* "Source card — chat AnswerView: 160px, number pill first, favicon, host,
|
|
21
|
+
* 3-line title".
|
|
22
|
+
*
|
|
23
|
+
* So density is kept by scrolling sideways rather than by discarding the text —
|
|
24
|
+
* the strip is one row tall whatever the count, which is what the grid was
|
|
25
|
+
* really buying. Both surfaces already scroll: `.ae-sources` is
|
|
26
|
+
* `display:flex; overflow-x:auto` at `newtab.css:260`.
|
|
27
|
+
*
|
|
28
|
+
* The number is not decoration. Both surfaces number the cards to match a
|
|
29
|
+
* marker in the prose, and the marker itself is not here: chat mints it with a
|
|
30
|
+
* remark plugin over private-use codepoints (`components/Web/plugin.ts`), which
|
|
31
|
+
* belongs to the markdown pipeline that stays with the surface.
|
|
14
32
|
*/
|
|
15
33
|
const gui_1 = require("@hanzo/gui");
|
|
16
34
|
const slot_1 = require("../backends/gui/slot.cjs");
|
|
17
|
-
|
|
35
|
+
/** Card width, px. The extension's is 168 and it cites chat's 160; the point of
|
|
36
|
+
* a fixed width is that a strip of them scans as a row rather than as ragged
|
|
37
|
+
* columns, so it is one number and not a range. */
|
|
38
|
+
const CARD = 168;
|
|
39
|
+
function Sources({ sources, title = 'Sources', onOpen, ...props }) {
|
|
18
40
|
if (sources.length === 0)
|
|
19
41
|
return null;
|
|
20
|
-
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('sources'), gap: "$2",
|
|
42
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('sources'), gap: "$2", ...props, 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, { ...(0, slot_1.slot)('sources-strip'), overflow: "scroll", contain: "content", gap: "$2", pb: "$1", children: sources.map((source, i) => ((0, jsx_runtime_1.jsx)(SourceCard, { source: source, index: i + 1, onOpen: onOpen }, source.id))) })] }));
|
|
21
43
|
}
|
|
22
|
-
function
|
|
44
|
+
function SourceCard({ source, index, onOpen, ...props }) {
|
|
23
45
|
const press = onOpen ? () => onOpen(source) : undefined;
|
|
24
|
-
|
|
46
|
+
const label = source.host ?? source.title;
|
|
47
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('source-card'), width: CARD, shrink: 0, gap: "$1.5", p: "$2.5", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$color2", 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: '$color4' } : undefined, ...props, children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1.5", children: [index != null ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color9", children: index })) : null, (0, jsx_runtime_1.jsx)(gui_1.XStack, { width: 14, height: 14, shrink: 0, items: "center", justify: "center", rounded: "$1", overflow: "hidden", bg: "$color4", children: source.icon ?? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color11", children: label.charAt(0).toUpperCase() })) }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color10", numberOfLines: 1, children: label })] }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color12", numberOfLines: 3, children: source.title })] }));
|
|
25
48
|
}
|
package/dist/chat/Sources.d.ts
CHANGED
|
@@ -1,23 +1,63 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Sources — the citations for a turn, as a strip of cards.
|
|
3
|
+
*
|
|
4
|
+
* This used to be a wrapping grid of 28px marks with the title reachable only
|
|
5
|
+
* as a tooltip, and the argument for it was density: sources are scanned for
|
|
6
|
+
* "which of these do I already trust", and twenty full-width titles push the
|
|
7
|
+
* rail past a screen. The density argument is right. Hiding the HOST was not,
|
|
8
|
+
* because the host is the answer to that exact question — a favicon is sixteen
|
|
9
|
+
* pixels of ambiguity and `nytimes.com` is a verdict — and neither surface that
|
|
10
|
+
* ships citations hides it. hanzo/chat's `SourceItem` (`components/Web/
|
|
11
|
+
* Sources.tsx`) draws favicon, domain, title and a snippet; the extension's
|
|
12
|
+
* `answer/Source.tsx:9-26` draws a number, a favicon, the host and a
|
|
13
|
+
* three-line-clamped title, and its own comment records where that came from:
|
|
14
|
+
* "Source card — chat AnswerView: 160px, number pill first, favicon, host,
|
|
15
|
+
* 3-line title".
|
|
16
|
+
*
|
|
17
|
+
* So density is kept by scrolling sideways rather than by discarding the text —
|
|
18
|
+
* the strip is one row tall whatever the count, which is what the grid was
|
|
19
|
+
* really buying. Both surfaces already scroll: `.ae-sources` is
|
|
20
|
+
* `display:flex; overflow-x:auto` at `newtab.css:260`.
|
|
21
|
+
*
|
|
22
|
+
* The number is not decoration. Both surfaces number the cards to match a
|
|
23
|
+
* marker in the prose, and the marker itself is not here: chat mints it with a
|
|
24
|
+
* remark plugin over private-use codepoints (`components/Web/plugin.ts`), which
|
|
25
|
+
* belongs to the markdown pipeline that stays with the surface.
|
|
26
|
+
*/
|
|
27
|
+
import { YStack } from '@hanzo/gui';
|
|
28
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
29
|
export interface Source {
|
|
3
30
|
id: string;
|
|
4
31
|
/** Accessible name and tooltip — a title, repo or file path. */
|
|
5
32
|
title: string;
|
|
6
33
|
/** Opened on press. Surfaces without navigation can omit it. */
|
|
7
34
|
href?: string;
|
|
8
|
-
/** Favicon or mark. Falls back to the first letter of `title`. */
|
|
35
|
+
/** Favicon or mark. Falls back to the first letter of `host` or `title`. */
|
|
9
36
|
icon?: ReactNode;
|
|
37
|
+
/**
|
|
38
|
+
* Who published it — `nytimes.com`, a repo, a filename. Shown above the
|
|
39
|
+
* title, because this is the line a reader actually scans.
|
|
40
|
+
*
|
|
41
|
+
* Derived by the SURFACE, not here. The extension parses it from the URL and
|
|
42
|
+
* strips `www.` (`Source.tsx:10-15`); chat is handed a domain by the server
|
|
43
|
+
* alongside a server-derived favicon. A `new URL()` in this package would be
|
|
44
|
+
* a third answer, and it would be the wrong one for a source that is a file
|
|
45
|
+
* path rather than a link.
|
|
46
|
+
*/
|
|
47
|
+
host?: string;
|
|
10
48
|
}
|
|
11
|
-
export interface SourcesProps {
|
|
49
|
+
export interface SourcesProps extends Omit<ComponentProps<typeof YStack>, 'children'> {
|
|
12
50
|
sources: Source[];
|
|
13
51
|
title?: string;
|
|
14
52
|
/** Raised on press. Given `href`, a surface may navigate instead. */
|
|
15
53
|
onOpen?: (source: Source) => void;
|
|
16
54
|
}
|
|
17
|
-
export declare function Sources({ sources, title, onOpen }: SourcesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
18
|
-
export interface
|
|
55
|
+
export declare function Sources({ sources, title, onOpen, ...props }: SourcesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
56
|
+
export interface SourceCardProps extends Omit<ComponentProps<typeof YStack>, 'children' | 'role'> {
|
|
19
57
|
source: Source;
|
|
58
|
+
/** Position in the list, 1-based — the number the prose's marker refers to. */
|
|
59
|
+
index?: number;
|
|
20
60
|
onOpen?: (source: Source) => void;
|
|
21
61
|
}
|
|
22
|
-
export declare function
|
|
62
|
+
export declare function SourceCard({ source, index, onOpen, ...props }: SourceCardProps): import("react/jsx-runtime").JSX.Element;
|
|
23
63
|
//# sourceMappingURL=Sources.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sources.d.ts","sourceRoot":"","sources":["../../src/chat/Sources.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Sources.d.ts","sourceRoot":"","sources":["../../src/chat/Sources.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAuB,MAAM,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAStD,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC;IACnF,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,GAAG,KAAK,EAAE,EAAE,YAAY,kDAiCrF;AAED,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC/F,MAAM,EAAE,MAAM,CAAA;IACd,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAED,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,2CA6D9E"}
|
package/dist/chat/Sources.js
CHANGED
|
@@ -1,22 +1,45 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* Sources — the
|
|
4
|
+
* Sources — the citations for a turn, as a strip of cards.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* This used to be a wrapping grid of 28px marks with the title reachable only
|
|
7
|
+
* as a tooltip, and the argument for it was density: sources are scanned for
|
|
8
|
+
* "which of these do I already trust", and twenty full-width titles push the
|
|
9
|
+
* rail past a screen. The density argument is right. Hiding the HOST was not,
|
|
10
|
+
* because the host is the answer to that exact question — a favicon is sixteen
|
|
11
|
+
* pixels of ambiguity and `nytimes.com` is a verdict — and neither surface that
|
|
12
|
+
* ships citations hides it. hanzo/chat's `SourceItem` (`components/Web/
|
|
13
|
+
* Sources.tsx`) draws favicon, domain, title and a snippet; the extension's
|
|
14
|
+
* `answer/Source.tsx:9-26` draws a number, a favicon, the host and a
|
|
15
|
+
* three-line-clamped title, and its own comment records where that came from:
|
|
16
|
+
* "Source card — chat AnswerView: 160px, number pill first, favicon, host,
|
|
17
|
+
* 3-line title".
|
|
18
|
+
*
|
|
19
|
+
* So density is kept by scrolling sideways rather than by discarding the text —
|
|
20
|
+
* the strip is one row tall whatever the count, which is what the grid was
|
|
21
|
+
* really buying. Both surfaces already scroll: `.ae-sources` is
|
|
22
|
+
* `display:flex; overflow-x:auto` at `newtab.css:260`.
|
|
23
|
+
*
|
|
24
|
+
* The number is not decoration. Both surfaces number the cards to match a
|
|
25
|
+
* marker in the prose, and the marker itself is not here: chat mints it with a
|
|
26
|
+
* remark plugin over private-use codepoints (`components/Web/plugin.ts`), which
|
|
27
|
+
* belongs to the markdown pipeline that stays with the surface.
|
|
10
28
|
*/
|
|
11
29
|
import { SizableText, XStack, YStack } from '@hanzo/gui';
|
|
12
30
|
import { slot, tip } from '../backends/gui/slot.js';
|
|
13
|
-
|
|
31
|
+
/** Card width, px. The extension's is 168 and it cites chat's 160; the point of
|
|
32
|
+
* a fixed width is that a strip of them scans as a row rather than as ragged
|
|
33
|
+
* columns, so it is one number and not a range. */
|
|
34
|
+
const CARD = 168;
|
|
35
|
+
export function Sources({ sources, title = 'Sources', onOpen, ...props }) {
|
|
14
36
|
if (sources.length === 0)
|
|
15
37
|
return null;
|
|
16
|
-
return (_jsxs(YStack, { ...slot('sources'), gap: "$2",
|
|
38
|
+
return (_jsxs(YStack, { ...slot('sources'), gap: "$2", ...props, 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, { ...slot('sources-strip'), overflow: "scroll", contain: "content", gap: "$2", pb: "$1", children: sources.map((source, i) => (_jsx(SourceCard, { source: source, index: i + 1, onOpen: onOpen }, source.id))) })] }));
|
|
17
39
|
}
|
|
18
|
-
export function
|
|
40
|
+
export function SourceCard({ source, index, onOpen, ...props }) {
|
|
19
41
|
const press = onOpen ? () => onOpen(source) : undefined;
|
|
20
|
-
|
|
42
|
+
const label = source.host ?? source.title;
|
|
43
|
+
return (_jsxs(YStack, { ...slot('source-card'), width: CARD, shrink: 0, gap: "$1.5", p: "$2.5", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$color2", 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: '$color4' } : undefined, ...props, children: [_jsxs(XStack, { items: "center", gap: "$1.5", children: [index != null ? (_jsx(SizableText, { size: "$1", color: "$color9", children: index })) : null, _jsx(XStack, { width: 14, height: 14, shrink: 0, items: "center", justify: "center", rounded: "$1", overflow: "hidden", bg: "$color4", children: source.icon ?? (_jsx(SizableText, { size: "$1", color: "$color11", children: label.charAt(0).toUpperCase() })) }), _jsx(SizableText, { size: "$1", color: "$color10", numberOfLines: 1, children: label })] }), _jsx(SizableText, { size: "$1", color: "$color12", numberOfLines: 3, children: source.title })] }));
|
|
21
44
|
}
|
|
22
45
|
//# sourceMappingURL=Sources.js.map
|
package/dist/chat/Sources.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sources.js","sourceRoot":"","sources":["../../src/chat/Sources.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ
|
|
1
|
+
{"version":3,"file":"Sources.js","sourceRoot":"","sources":["../../src/chat/Sources.tsx"],"names":[],"mappings":"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"}
|
package/dist/chat/Step.cjs
CHANGED
|
@@ -65,7 +65,7 @@ const mark = (status) => {
|
|
|
65
65
|
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Ban, { size: MARK, color: "$color11" });
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
|
-
function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, }) {
|
|
68
|
+
function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, ...props }) {
|
|
69
69
|
// A step with no body is a statement, not a control. Rendering a dead chevron
|
|
70
70
|
// and a focusable trigger over nothing is how a keyboard user is sent to a
|
|
71
71
|
// stop that does not answer.
|
|
@@ -77,5 +77,5 @@ function Step({ name, status = 'done', detail, children, defaultOpen, open, onOp
|
|
|
77
77
|
// its `stopped` register with a border rather than a fill. A step that
|
|
78
78
|
// errored is set apart the same way, so it still reads as a failure in a
|
|
79
79
|
// brand that retunes the whole ramp.
|
|
80
|
-
borderColor: status === 'error' ? '$color9' : '$borderColor', bg: "$color2", overflow: "hidden", children: [opens ? (0, jsx_runtime_1.jsx)(gui_2.CollapsibleTrigger, { width: "100%", children: header }) : header, opens ? ((0, jsx_runtime_1.jsx)(gui_2.CollapsibleContent, { children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('step-body'), px: "$3", py: "$2.5", gap: "$2", borderTopWidth: 1, borderColor: "$borderColor", children: children }) })) : null] }));
|
|
80
|
+
borderColor: status === 'error' ? '$color9' : '$borderColor', bg: "$color2", overflow: "hidden", ...props, children: [opens ? (0, jsx_runtime_1.jsx)(gui_2.CollapsibleTrigger, { width: "100%", children: header }) : header, opens ? ((0, jsx_runtime_1.jsx)(gui_2.CollapsibleContent, { children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('step-body'), px: "$3", py: "$2.5", gap: "$2", borderTopWidth: 1, borderColor: "$borderColor", children: children }) })) : null] }));
|
|
81
81
|
}
|
package/dist/chat/Step.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
import { Collapsible } from '../backends/gui/index.js';
|
|
2
3
|
/**
|
|
3
4
|
* How a step went.
|
|
4
5
|
*
|
|
@@ -10,7 +11,7 @@ import type { ReactNode } from 'react';
|
|
|
10
11
|
* step that is running are both "not yet".
|
|
11
12
|
*/
|
|
12
13
|
export type Ran = 'running' | 'done' | 'error' | 'cancelled';
|
|
13
|
-
export interface StepProps {
|
|
14
|
+
export interface StepProps extends Omit<ComponentProps<typeof Collapsible>, 'children' | 'open' | 'defaultOpen' | 'onOpenChange'> {
|
|
14
15
|
/** What ran — a tool name, "Reasoning", "Plan". */
|
|
15
16
|
name: string;
|
|
16
17
|
status?: Ran;
|
|
@@ -30,5 +31,5 @@ export interface StepProps {
|
|
|
30
31
|
open?: boolean;
|
|
31
32
|
onOpenChange?: (open: boolean) => void;
|
|
32
33
|
}
|
|
33
|
-
export declare function Step({ name, status, detail, children, defaultOpen, open, onOpenChange, }: StepProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export declare function Step({ name, status, detail, children, defaultOpen, open, onOpenChange, ...props }: StepProps): import("react/jsx-runtime").JSX.Element;
|
|
34
35
|
//# sourceMappingURL=Step.d.ts.map
|
package/dist/chat/Step.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Step.d.ts","sourceRoot":"","sources":["../../src/chat/Step.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"Step.d.ts","sourceRoot":"","sources":["../../src/chat/Step.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,WAAW,EAAmD,MAAM,iBAAiB,CAAA;AAG9F;;;;;;;;;GASG;AACH,MAAM,MAAM,GAAG,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CAAA;AA8B5D,MAAM,WAAW,SACf,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,cAAc,CAAC;IACtG,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,GAAG,CAAA;IACZ;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;kEAC8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,oBAAoB;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC;AAED,wBAAgB,IAAI,CAAC,EACnB,IAAI,EACJ,MAAe,EACf,MAAM,EACN,QAAQ,EACR,WAAW,EACX,IAAI,EACJ,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,SAAS,2CA6DX"}
|
package/dist/chat/Step.js
CHANGED
|
@@ -62,7 +62,7 @@ const mark = (status) => {
|
|
|
62
62
|
return _jsx(Ban, { size: MARK, color: "$color11" });
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
|
-
export function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, }) {
|
|
65
|
+
export function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, ...props }) {
|
|
66
66
|
// A step with no body is a statement, not a control. Rendering a dead chevron
|
|
67
67
|
// and a focusable trigger over nothing is how a keyboard user is sent to a
|
|
68
68
|
// stop that does not answer.
|
|
@@ -74,6 +74,6 @@ export function Step({ name, status = 'done', detail, children, defaultOpen, ope
|
|
|
74
74
|
// its `stopped` register with a border rather than a fill. A step that
|
|
75
75
|
// errored is set apart the same way, so it still reads as a failure in a
|
|
76
76
|
// brand that retunes the whole ramp.
|
|
77
|
-
borderColor: status === 'error' ? '$color9' : '$borderColor', bg: "$color2", overflow: "hidden", children: [opens ? _jsx(CollapsibleTrigger, { width: "100%", children: header }) : header, opens ? (_jsx(CollapsibleContent, { children: _jsx(YStack, { ...slot('step-body'), px: "$3", py: "$2.5", gap: "$2", borderTopWidth: 1, borderColor: "$borderColor", children: children }) })) : null] }));
|
|
77
|
+
borderColor: status === 'error' ? '$color9' : '$borderColor', bg: "$color2", overflow: "hidden", ...props, children: [opens ? _jsx(CollapsibleTrigger, { width: "100%", children: header }) : header, opens ? (_jsx(CollapsibleContent, { children: _jsx(YStack, { ...slot('step-body'), px: "$3", py: "$2.5", gap: "$2", borderTopWidth: 1, borderColor: "$borderColor", children: children }) })) : null] }));
|
|
78
78
|
}
|
|
79
79
|
//# sourceMappingURL=Step.js.map
|
package/dist/chat/Step.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Step.js","sourceRoot":"","sources":["../../src/chat/Step.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAGjF,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9F,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAc3C;sEACsE;AACtE,MAAM,IAAI,GAAG,EAAE,CAAA;AAEf;;;;;;;;;;GAUG;AACH,MAAM,IAAI,GAAG,CAAC,MAAW,EAAE,EAAE;IAC3B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,KAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAC,UAAU,GAAG,CAAA;QACjD,KAAK,MAAM;YACT,OAAO,KAAC,KAAK,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAC,UAAU,GAAG,CAAA;QAC/C,KAAK,OAAO;YACV,OAAO,KAAC,aAAa,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAC,UAAU,GAAG,CAAA;QACvD,KAAK,WAAW;YACd,OAAO,KAAC,GAAG,IAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAC,UAAU,GAAG,CAAA;IAC/C,CAAC;AACH,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"Step.js","sourceRoot":"","sources":["../../src/chat/Step.tsx"],"names":[],"mappings":"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"}
|
package/dist/chat/Thread.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';"use strict";
|
|
2
2
|
'use client';
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.Thread =
|
|
4
|
+
exports.Thread = void 0;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
6
|
/**
|
|
7
7
|
* Thread — the scrolling column of turns.
|
|
@@ -10,6 +10,28 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
10
10
|
* to the bottom, and stop following the instant the reader scrolls up. The
|
|
11
11
|
* decision is `pinned()`, asserted without a DOM; this component only wires it
|
|
12
12
|
* to the platform's scroll view, so momentum and keyboard stay the host's.
|
|
13
|
+
*
|
|
14
|
+
* That decision is now the fleet's only answer to "am I at the bottom", which
|
|
15
|
+
* had five: 50px in two places, 97%-of-height in a third, an
|
|
16
|
+
* `IntersectionObserver` at a 0.85 ratio in a fourth, and on the thread itself
|
|
17
|
+
* nothing at all — hanzo.app `/chat` ran `scrollIntoView({behavior:'smooth'})`
|
|
18
|
+
* on every `messages` change, and since a streaming turn rewrites `messages`
|
|
19
|
+
* per SSE delta, scrolling up to re-read was undone several times a second.
|
|
20
|
+
*
|
|
21
|
+
* Measured in Chromium against the packed tarball, 2500 tokens at 4ms:
|
|
22
|
+
* following holds a 0px gap through 2501 commits; parked at offset 0 the reader
|
|
23
|
+
* STAYS at 0 while content grows 1015 → 1375; returning to the end resumes
|
|
24
|
+
* following at 0px.
|
|
25
|
+
*
|
|
26
|
+
* There is no `onLayout` here any more, and nothing is lost with it. It was
|
|
27
|
+
* passed to keep a `track` ref current, gui does not implement it on this
|
|
28
|
+
* component so React forwarded it to the DOM as an unknown handler — the noise
|
|
29
|
+
* hanzo.app reported — and the ref it fed was WRITE-ONLY: `track` was read in
|
|
30
|
+
* exactly one place, `onScroll`, which rebuilds all three numbers from the
|
|
31
|
+
* event before reading them. So the handler was dead, the state it kept was
|
|
32
|
+
* dead, and the measurement the two together looked like they were doing was
|
|
33
|
+
* being done properly a few lines below the whole time. The scroll event
|
|
34
|
+
* carries `layoutMeasurement`; nothing else needs to ask.
|
|
13
35
|
*/
|
|
14
36
|
const gui_1 = require("@hanzo/gui");
|
|
15
37
|
const react_1 = require("react");
|
|
@@ -17,26 +39,29 @@ const slot_1 = require("../backends/gui/slot.cjs");
|
|
|
17
39
|
const stick_1 = require("./stick.cjs");
|
|
18
40
|
/** Reading-measure cap for prose, in px. */
|
|
19
41
|
const MEASURE = 768;
|
|
20
|
-
function Thread({ children, maxWidth = MEASURE, slack = stick_1.SLACK, gap = 24 }) {
|
|
42
|
+
exports.Thread = (0, react_1.forwardRef)(function Thread({ children, maxWidth = MEASURE, slack = stick_1.SLACK, gap = 24, onScroll, column, ...props }, ref) {
|
|
21
43
|
const view = (0, react_1.useRef)(null);
|
|
22
|
-
const track = (0, react_1.useRef)({ offset: 0, viewport: 0, content: 0 });
|
|
23
44
|
const follow = (0, react_1.useRef)(true);
|
|
45
|
+
// Ours to scroll with, the caller's because three consumers need this node.
|
|
46
|
+
const hold = (0, react_1.useCallback)((el) => {
|
|
47
|
+
view.current = el;
|
|
48
|
+
if (typeof ref === 'function')
|
|
49
|
+
ref(el);
|
|
50
|
+
else if (ref)
|
|
51
|
+
ref.current = el;
|
|
52
|
+
}, [ref]);
|
|
24
53
|
const grew = (0, react_1.useCallback)(() => {
|
|
25
54
|
if (follow.current)
|
|
26
55
|
view.current?.scrollToEnd({ animated: false });
|
|
27
56
|
}, []);
|
|
28
|
-
return ((0, jsx_runtime_1.jsx)(gui_1.ScrollView, { ref:
|
|
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) => {
|
|
57
|
+
return ((0, jsx_runtime_1.jsx)(gui_1.ScrollView, { ref: hold, ...(0, slot_1.slot)('thread'), flex: 1, width: "100%", scrollEventThrottle: 16, onContentSizeChange: grew, onScroll: (e) => {
|
|
34
58
|
const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent;
|
|
35
|
-
track
|
|
59
|
+
const track = {
|
|
36
60
|
offset: contentOffset.y,
|
|
37
61
|
viewport: layoutMeasurement.height,
|
|
38
62
|
content: contentSize.height,
|
|
39
63
|
};
|
|
40
|
-
follow.current = (0, stick_1.pinned)(track
|
|
41
|
-
|
|
42
|
-
}
|
|
64
|
+
follow.current = (0, stick_1.pinned)(track, slack);
|
|
65
|
+
onScroll?.(e, { pinned: follow.current, track });
|
|
66
|
+
}, ...props, 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), ...column, children: children }) }));
|
|
67
|
+
});
|