@hanzo/ui 8.1.4 → 8.1.6
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 +5 -10
- package/dist/backends/gui/textarea.d.ts +11 -32
- package/dist/backends/gui/textarea.d.ts.map +1 -1
- package/dist/backends/gui/textarea.js +5 -10
- 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 +17 -47
- package/dist/chat/Composer.d.ts +40 -3
- package/dist/chat/Composer.d.ts.map +1 -1
- package/dist/chat/Composer.js +17 -47
- package/dist/chat/Composer.js.map +1 -1
- package/dist/chat/Failure.cjs +11 -30
- package/dist/chat/Failure.d.ts +15 -3
- package/dist/chat/Failure.d.ts.map +1 -1
- package/dist/chat/Failure.js +11 -30
- 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 +16 -33
- package/dist/chat/Message.d.ts +26 -15
- package/dist/chat/Message.d.ts.map +1 -1
- package/dist/chat/Message.js +16 -33
- package/dist/chat/Message.js.map +1 -1
- package/dist/chat/Sources.cjs +15 -10
- package/dist/chat/Sources.d.ts +26 -6
- package/dist/chat/Sources.d.ts.map +1 -1
- package/dist/chat/Sources.js +14 -9
- package/dist/chat/Sources.js.map +1 -1
- package/dist/chat/Step.cjs +18 -44
- package/dist/chat/Step.d.ts +9 -20
- package/dist/chat/Step.d.ts.map +1 -1
- package/dist/chat/Step.js +18 -44
- package/dist/chat/Step.js.map +1 -1
- package/dist/chat/Thread.cjs +19 -17
- package/dist/chat/Thread.d.ts +25 -3
- package/dist/chat/Thread.d.ts.map +1 -1
- package/dist/chat/Thread.js +19 -17
- package/dist/chat/Thread.js.map +1 -1
- package/dist/chat/index.cjs +22 -46
- package/dist/chat/index.d.ts +21 -45
- package/dist/chat/index.d.ts.map +1 -1
- package/dist/chat/index.js +21 -45
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/pure.cjs +22 -0
- package/dist/chat/pure.d.ts +3 -0
- package/dist/chat/pure.d.ts.map +1 -0
- package/dist/chat/pure.js +16 -0
- package/dist/chat/pure.js.map +1 -0
- package/dist/chat/send.cjs +12 -13
- package/dist/chat/send.d.ts +8 -6
- package/dist/chat/send.d.ts.map +1 -1
- package/dist/chat/send.js +12 -13
- package/dist/chat/send.js.map +1 -1
- package/dist/chat/stick.cjs +3 -5
- package/dist/chat/stick.d.ts +2 -4
- package/dist/chat/stick.d.ts.map +1 -1
- package/dist/chat/stick.js +3 -5
- package/dist/chat/stick.js.map +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 +6 -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 +10 -1
- package/dist/product/pure.d.ts +2 -0
- package/dist/product/pure.d.ts.map +1 -1
- package/dist/product/pure.js +5 -0
- package/dist/product/pure.js.map +1 -1
- package/dist/styles.css +14 -2
- package/package.json +7 -1
package/dist/chat/Failure.js
CHANGED
|
@@ -1,46 +1,27 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* Failure — the turn did not
|
|
4
|
+
* Failure — the turn did not arrive, and what to do about it.
|
|
5
5
|
*
|
|
6
6
|
* Distinct from a `Step` that errored: a step can fail inside an answer that
|
|
7
|
-
* still
|
|
8
|
-
*
|
|
9
|
-
* swapping the whole body for `ErrorMessage`.
|
|
7
|
+
* still lands. Retry sits beside the message, not in the hover strip, so it is
|
|
8
|
+
* reachable on a touch device.
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* again" (`ask-ai/chat-thread.tsx:258`), the extension's `.ae-error` div
|
|
15
|
-
* (`AnswerEngine.tsx:336`), and hanzo.app `/chat`, which is the interesting
|
|
16
|
-
* one: it sets `Message.error` at `app/chat/page.tsx:292` and never reads it
|
|
17
|
-
* anywhere in the render, so a stream that dies reports through a detached
|
|
18
|
-
* banner and the turn itself says nothing.
|
|
19
|
-
*
|
|
20
|
-
* Two of the four offer a way to try again. Both put it next to the message
|
|
21
|
-
* rather than in the hover strip, because a hover affordance on the thing that
|
|
22
|
-
* just failed is not reachable on a touch device.
|
|
23
|
-
*
|
|
24
|
-
* `role="alert"` with `aria-live="assertive"` is chat's, and it is right: a
|
|
25
|
-
* turn failing is the one event in a conversation that has to interrupt, since
|
|
26
|
-
* the reader is waiting on prose that is never going to come.
|
|
10
|
+
* `role="alert"` with `aria-live="assertive"`: the reader is waiting on prose
|
|
11
|
+
* that is never coming, which is the one event in a conversation that has to
|
|
12
|
+
* interrupt.
|
|
27
13
|
*/
|
|
28
14
|
import { XStack, YStack } from '@hanzo/gui';
|
|
29
15
|
import { RefreshCw } from '@hanzogui/lucide-icons-2';
|
|
30
16
|
import { Button } from '../backends/gui/index.js';
|
|
31
17
|
import { ink } from '../backends/gui/ink.js';
|
|
32
18
|
import { slot } from '../backends/gui/slot.js';
|
|
33
|
-
export function Failure({ children, onRetry, retryLabel = 'Try again' }) {
|
|
19
|
+
export function Failure({ children, onRetry, retryLabel = 'Try again', ...props }) {
|
|
34
20
|
return (_jsxs(YStack, { ...slot('failure'), role: "alert", "aria-live": "assertive", width: "100%", gap: "$2", px: "$3", py: "$2.5", rounded: "$4", borderWidth: 1,
|
|
35
|
-
// The
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// The real Button, not a `role="button"` box with an `onPress`. A View
|
|
40
|
-
// wearing the role takes focus and then does nothing on Enter or Space,
|
|
41
|
-
// because the activation behaviour belongs to the element and not to
|
|
42
|
-
// the attribute — and the one control on a failed turn is the last one
|
|
43
|
-
// that should be pointer-only.
|
|
21
|
+
// The `stopped` register from `product/tone.ts`: an outline, not a hue.
|
|
22
|
+
borderColor: "$color9", bg: "$color4", ...props, children: [ink(children, undefined, { size: '$2', color: '$color12' }), onRetry ? (
|
|
23
|
+
// A real Button: a View wearing `role="button"` takes focus and then
|
|
24
|
+
// ignores Enter and Space.
|
|
44
25
|
_jsx(XStack, { self: "flex-start", children: _jsxs(Button, { ...slot('failure-retry'), variant: "outline", size: "sm", onPress: onRetry, children: [_jsx(RefreshCw, { size: 13 }), retryLabel] }) })) : null] }));
|
|
45
26
|
}
|
|
46
27
|
//# sourceMappingURL=Failure.js.map
|
package/dist/chat/Failure.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Failure.js","sourceRoot":"","sources":["../../src/chat/Failure.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ
|
|
1
|
+
{"version":3,"file":"Failure.js","sourceRoot":"","sources":["../../src/chat/Failure.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGpD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAU3C,MAAM,UAAU,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,WAAW,EAAE,GAAG,KAAK,EAAgB;IAC7F,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,EACnB,IAAI,EAAC,OAAO,eACF,WAAW,EACrB,KAAK,EAAC,MAAM,EACZ,GAAG,EAAC,IAAI,EACR,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,MAAM,EACT,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC;QACd,wEAAwE;QACxE,WAAW,EAAC,SAAS,EACrB,EAAE,EAAC,SAAS,KACR,KAAK,aAER,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAC3D,OAAO,CAAC,CAAC,CAAC;YACT,qEAAqE;YACrE,2BAA2B;YAC3B,KAAC,MAAM,IAAC,IAAI,EAAC,YAAY,YACvB,MAAC,MAAM,OAAK,IAAI,CAAC,eAAe,CAAC,EAAE,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,OAAO,aAC7E,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,EACtB,UAAU,IACJ,GACF,CACV,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAA;AACH,CAAC"}
|
package/dist/chat/Header.cjs
CHANGED
|
@@ -18,8 +18,8 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
18
18
|
const gui_1 = require("@hanzo/gui");
|
|
19
19
|
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
20
20
|
const slot_1 = require("../backends/gui/slot.cjs");
|
|
21
|
-
function Header({ title, onOpenMenu, children }) {
|
|
22
|
-
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('chat-header'), width: "100%", height: 48, shrink: 0, items: "center", gap: "$2", px: "$3", borderBottomWidth: 1, borderColor: "$borderColor", bg: "$background", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1", shrink: 1, children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", fontWeight: "500", numberOfLines: 1, children: title }), onOpenMenu ? ((0, jsx_runtime_1.jsx)(HeaderButton, { label: "Conversation options", onPress: onOpenMenu, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Ellipsis, { size: 16 }) })) : null] }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1 }), children] }));
|
|
21
|
+
function Header({ title, onOpenMenu, children, leading, ...props }) {
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('chat-header'), width: "100%", height: 48, shrink: 0, items: "center", gap: "$2", px: "$3", borderBottomWidth: 1, borderColor: "$borderColor", bg: "$background", ...props, children: [leading, (0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1", shrink: 1, children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", fontWeight: "500", numberOfLines: 1, children: title }), onOpenMenu ? ((0, jsx_runtime_1.jsx)(HeaderButton, { label: "Conversation options", onPress: onOpenMenu, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Ellipsis, { size: 16 }) })) : null] }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1 }), children] }));
|
|
23
23
|
}
|
|
24
24
|
function HeaderButton({ label, onPress, children }) {
|
|
25
25
|
return ((0, jsx_runtime_1.jsx)(gui_1.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, ...(0, slot_1.tip)(label), hoverStyle: { bg: '$color4', opacity: 1 }, pressStyle: { bg: '$color5' }, children: children }));
|
package/dist/chat/Header.d.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Header — the conversation title bar.
|
|
3
|
+
*
|
|
4
|
+
* Title on the left, `children` as the action slot on the right. The actions are
|
|
5
|
+
* a slot rather than a fixed set because what belongs there is per-surface:
|
|
6
|
+
* hanzo.chat shares and opens a details rail, the console shows the owning
|
|
7
|
+
* project, hanzo.app shows neither.
|
|
8
|
+
*/
|
|
9
|
+
import { XStack } from '@hanzo/gui';
|
|
10
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
11
|
+
export interface HeaderProps extends Omit<ComponentProps<typeof XStack>, 'children'> {
|
|
3
12
|
title: string;
|
|
4
13
|
/** Overflow menu next to the title. Omit to hide it. */
|
|
5
14
|
onOpenMenu?: () => void;
|
|
6
15
|
/** Action slot, rendered at the end of the row. */
|
|
7
16
|
children?: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Slot BEFORE the title — a rail toggle, a back arrow.
|
|
19
|
+
*
|
|
20
|
+
* hanzo.app `/chat` leads with a sidebar toggle and kept its own header
|
|
21
|
+
* rather than adopt this one, because the row began at the title and there
|
|
22
|
+
* was nowhere to put it.
|
|
23
|
+
*/
|
|
24
|
+
leading?: ReactNode;
|
|
8
25
|
}
|
|
9
|
-
export declare function Header({ title, onOpenMenu, children }: HeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export declare function Header({ title, onOpenMenu, children, leading, ...props }: HeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
10
27
|
export interface HeaderButtonProps {
|
|
11
28
|
/** Required — the accessible name for an icon-only control. */
|
|
12
29
|
label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/chat/Header.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/chat/Header.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,OAAO,EAAe,MAAM,EAAU,MAAM,YAAY,CAAA;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItD,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC;IAClF,KAAK,EAAE,MAAM,CAAA;IACb,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,MAAM,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW,2CAmCrF;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CAqB3E;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,KAAe,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CAuBzE;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,wBAAgB,WAAW,CAAC,EAAE,KAA8B,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CAMxF;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAW,EAAE,EAAE,UAAU,2CAe1D"}
|
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
|
@@ -9,55 +9,38 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
9
9
|
*
|
|
10
10
|
* Role drives presentation and nothing else: a user turn is a contained bubble
|
|
11
11
|
* that shrinks to its content, an assistant turn is full-bleed prose, a system
|
|
12
|
-
* turn is a muted aside.
|
|
13
|
-
*
|
|
14
|
-
* belongs in a presentational package.
|
|
12
|
+
* turn is a muted aside. The contrast is what says who is speaking, so there is
|
|
13
|
+
* no name and no timestamp, and `icon` is opt-in.
|
|
15
14
|
*
|
|
16
|
-
*
|
|
17
|
-
* renderers across the estate independently arrived at. hanzo/chat states it
|
|
18
|
-
* outright in `client/src/components/Chat/Messages/ui/MessageRender.tsx:131`:
|
|
19
|
-
* "the user's turn is a glass bubble on the right, the reply plain and full
|
|
20
|
-
* width — the contrast is what says who is speaking." No avatar, no sender
|
|
21
|
-
* name, no timestamp — which is why `icon` is opt-in and there is no `name`
|
|
22
|
-
* prop. Only the read-only share view renders a name, and only one surface
|
|
23
|
-
* renders a timestamp.
|
|
15
|
+
* Content is `children`: the markdown pipeline stays with the surface.
|
|
24
16
|
*/
|
|
25
17
|
const gui_1 = require("@hanzo/gui");
|
|
26
18
|
const ink_1 = require("../backends/gui/ink.cjs");
|
|
27
19
|
const slot_1 = require("../backends/gui/slot.cjs");
|
|
28
20
|
/**
|
|
29
|
-
* The mark that says a turn is still arriving.
|
|
21
|
+
* The mark that says a turn is still arriving. Static, not blinking.
|
|
30
22
|
*
|
|
31
|
-
* Placed by whoever knows where the prose ends
|
|
32
|
-
* owns that node and can append this inside it
|
|
33
|
-
* end of the turn
|
|
34
|
-
*
|
|
35
|
-
* It does not blink. Every surface that ships one draws it static — an 8x16
|
|
36
|
-
* block on hanzo.app `/chat`, a 2px caret in the builder, a 12px `⬤` from
|
|
37
|
-
* hanzo/chat's `.result-streaming::after`. A caret is the narrowest of the
|
|
38
|
-
* three and the one that reads as "the sentence continues" rather than as a
|
|
39
|
-
* bullet. Decorative, so it is hidden from assistive tech: the turn's text is
|
|
40
|
-
* already live-announced by the surface, and a cursor announced as content is
|
|
41
|
-
* noise on every token.
|
|
23
|
+
* Placed by whoever knows where the prose ends: a surface rendering markdown
|
|
24
|
+
* owns that node and can append this inside it, and `Message busy` puts it at
|
|
25
|
+
* the end of the turn. Decorative, so assistive tech skips it — the surface
|
|
26
|
+
* already live-announces the text.
|
|
42
27
|
*/
|
|
43
28
|
function Caret() {
|
|
44
29
|
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
30
|
}
|
|
46
|
-
function Message({ role, children, actions, busy = false, icon }) {
|
|
31
|
+
function Message({ role, children, actions, busy = false, icon, body, ...props }) {
|
|
47
32
|
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 }) }));
|
|
33
|
+
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
34
|
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",
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
//
|
|
55
|
-
// (`ask-ai/chat-thread.tsx:141`). This package said 80% and no one
|
|
56
|
-
// said 80%.
|
|
35
|
+
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",
|
|
36
|
+
// Makes `actions` revealable with `$group-hover`. Unnamed: gui types
|
|
37
|
+
// `group` as a boolean, so a name does not compile.
|
|
38
|
+
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",
|
|
39
|
+
// 85% is what the surfaces converged on for a user turn.
|
|
57
40
|
maxW: mine ? '85%' : '100%', flex: mine ? undefined : 1, ...(mine && {
|
|
58
41
|
bg: '$color3',
|
|
59
42
|
rounded: '$5',
|
|
60
43
|
px: '$3',
|
|
61
44
|
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] })] }));
|
|
45
|
+
}), ...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
46
|
}
|
package/dist/chat/Message.d.ts
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
export type Role = 'user' | 'assistant' | 'system';
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
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. The contrast is what says who is speaking, so there is
|
|
7
|
+
* no name and no timestamp, and `icon` is opt-in.
|
|
5
8
|
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
* Content is `children`: the markdown pipeline stays with the surface.
|
|
10
|
+
*/
|
|
11
|
+
import { XStack } from '@hanzo/gui';
|
|
12
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
13
|
+
export type Role = 'user' | 'assistant' | 'system';
|
|
14
|
+
/** What a gui stack accepts. `role` is dropped: here it names the speaker, not
|
|
15
|
+
* an ARIA role. `aria-label` still reaches the row. */
|
|
16
|
+
type Stack = Omit<ComponentProps<typeof XStack>, 'children' | 'role'>;
|
|
17
|
+
/**
|
|
18
|
+
* The mark that says a turn is still arriving. Static, not blinking.
|
|
9
19
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* bullet. Decorative, so it is hidden from assistive tech: the turn's text is
|
|
15
|
-
* already live-announced by the surface, and a cursor announced as content is
|
|
16
|
-
* noise on every token.
|
|
20
|
+
* Placed by whoever knows where the prose ends: a surface rendering markdown
|
|
21
|
+
* owns that node and can append this inside it, and `Message busy` puts it at
|
|
22
|
+
* the end of the turn. Decorative, so assistive tech skips it — the surface
|
|
23
|
+
* already live-announces the text.
|
|
17
24
|
*/
|
|
18
25
|
export declare function Caret(): import("react/jsx-runtime").JSX.Element;
|
|
19
|
-
export interface MessageProps {
|
|
26
|
+
export interface MessageProps extends Stack {
|
|
20
27
|
role: Role;
|
|
21
28
|
children?: ReactNode;
|
|
22
29
|
/** Row rendered under the turn — copy, retry, feedback. */
|
|
@@ -25,6 +32,10 @@ export interface MessageProps {
|
|
|
25
32
|
busy?: boolean;
|
|
26
33
|
/** Leading affordance for an assistant turn: avatar or model mark. */
|
|
27
34
|
icon?: ReactNode;
|
|
35
|
+
/** The bubble's own props — the inner box, not the row. Reaches the fill, the
|
|
36
|
+
* corner and the width cap. Absent, nothing changes. */
|
|
37
|
+
body?: Stack;
|
|
28
38
|
}
|
|
29
|
-
export declare function Message({ role, children, actions, busy, icon }: MessageProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare function Message({ role, children, actions, busy, icon, body, ...props }: MessageProps): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export {};
|
|
30
41
|
//# 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;;;;;;;;;GASG;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;wDACwD;AACxD,KAAK,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,CAAA;AAErE;;;;;;;GAOG;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;6DACyD;IACzD,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,2CAoDd"}
|
package/dist/chat/Message.js
CHANGED
|
@@ -5,56 +5,39 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
5
5
|
*
|
|
6
6
|
* Role drives presentation and nothing else: a user turn is a contained bubble
|
|
7
7
|
* that shrinks to its content, an assistant turn is full-bleed prose, a system
|
|
8
|
-
* turn is a muted aside.
|
|
9
|
-
*
|
|
10
|
-
* belongs in a presentational package.
|
|
8
|
+
* turn is a muted aside. The contrast is what says who is speaking, so there is
|
|
9
|
+
* no name and no timestamp, and `icon` is opt-in.
|
|
11
10
|
*
|
|
12
|
-
*
|
|
13
|
-
* renderers across the estate independently arrived at. hanzo/chat states it
|
|
14
|
-
* outright in `client/src/components/Chat/Messages/ui/MessageRender.tsx:131`:
|
|
15
|
-
* "the user's turn is a glass bubble on the right, the reply plain and full
|
|
16
|
-
* width — the contrast is what says who is speaking." No avatar, no sender
|
|
17
|
-
* name, no timestamp — which is why `icon` is opt-in and there is no `name`
|
|
18
|
-
* prop. Only the read-only share view renders a name, and only one surface
|
|
19
|
-
* renders a timestamp.
|
|
11
|
+
* Content is `children`: the markdown pipeline stays with the surface.
|
|
20
12
|
*/
|
|
21
13
|
import { Text, XStack, YStack } from '@hanzo/gui';
|
|
22
14
|
import { ink } from '../backends/gui/ink.js';
|
|
23
15
|
import { slot } from '../backends/gui/slot.js';
|
|
24
16
|
/**
|
|
25
|
-
* The mark that says a turn is still arriving.
|
|
17
|
+
* The mark that says a turn is still arriving. Static, not blinking.
|
|
26
18
|
*
|
|
27
|
-
* Placed by whoever knows where the prose ends
|
|
28
|
-
* owns that node and can append this inside it
|
|
29
|
-
* end of the turn
|
|
30
|
-
*
|
|
31
|
-
* It does not blink. Every surface that ships one draws it static — an 8x16
|
|
32
|
-
* block on hanzo.app `/chat`, a 2px caret in the builder, a 12px `⬤` from
|
|
33
|
-
* hanzo/chat's `.result-streaming::after`. A caret is the narrowest of the
|
|
34
|
-
* three and the one that reads as "the sentence continues" rather than as a
|
|
35
|
-
* bullet. Decorative, so it is hidden from assistive tech: the turn's text is
|
|
36
|
-
* already live-announced by the surface, and a cursor announced as content is
|
|
37
|
-
* noise on every token.
|
|
19
|
+
* Placed by whoever knows where the prose ends: a surface rendering markdown
|
|
20
|
+
* owns that node and can append this inside it, and `Message busy` puts it at
|
|
21
|
+
* the end of the turn. Decorative, so assistive tech skips it — the surface
|
|
22
|
+
* already live-announces the text.
|
|
38
23
|
*/
|
|
39
24
|
export function Caret() {
|
|
40
25
|
return _jsx(YStack, { ...slot('caret'), width: 2, height: 15, rounded: 1, bg: "$color12", "aria-hidden": true });
|
|
41
26
|
}
|
|
42
|
-
export function Message({ role, children, actions, busy = false, icon }) {
|
|
27
|
+
export function Message({ role, children, actions, busy = false, icon, body, ...props }) {
|
|
43
28
|
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 }) }));
|
|
29
|
+
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
30
|
const mine = role === 'user';
|
|
46
|
-
return (_jsxs(XStack, { ...slot('message'), "data-role": role, width: "100%", justify: mine ? 'flex-end' : 'flex-start', gap: "$2",
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
//
|
|
51
|
-
// (`ask-ai/chat-thread.tsx:141`). This package said 80% and no one
|
|
52
|
-
// said 80%.
|
|
31
|
+
return (_jsxs(XStack, { ...slot('message'), "data-role": role, width: "100%", justify: mine ? 'flex-end' : 'flex-start', gap: "$2",
|
|
32
|
+
// Makes `actions` revealable with `$group-hover`. Unnamed: gui types
|
|
33
|
+
// `group` as a boolean, so a name does not compile.
|
|
34
|
+
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",
|
|
35
|
+
// 85% is what the surfaces converged on for a user turn.
|
|
53
36
|
maxW: mine ? '85%' : '100%', flex: mine ? undefined : 1, ...(mine && {
|
|
54
37
|
bg: '$color3',
|
|
55
38
|
rounded: '$5',
|
|
56
39
|
px: '$3',
|
|
57
40
|
py: '$2',
|
|
58
|
-
}), children: [ink(children), busy ? _jsx(Caret, {}) : null, actions ? _jsx(XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
41
|
+
}), ...body, children: [ink(children), busy ? _jsx(Caret, {}) : null, actions ? _jsx(XStack, { gap: "$1", items: "center", children: actions }) : null] })] }));
|
|
59
42
|
}
|
|
60
43
|
//# 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
|
|
1
|
+
{"version":3,"file":"Message.js","sourceRoot":"","sources":["../../src/chat/Message.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;GASG;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;AAQ3C;;;;;;;GAOG;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;AAgBD,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,qEAAqE;QACrE,oDAAoD;QACpD,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,yDAAyD;gBACzD,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,29 @@
|
|
|
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
|
+
* Each card leads with the host, which is what a reader scans to decide whether
|
|
11
|
+
* they trust a source; the title is the tiebreaker under it. The strip scrolls
|
|
12
|
+
* sideways so it stays one row tall at any count.
|
|
13
|
+
*
|
|
14
|
+
* The number matches a marker in the prose. Minting that marker belongs to the
|
|
15
|
+
* markdown pipeline, which stays with the surface.
|
|
14
16
|
*/
|
|
15
17
|
const gui_1 = require("@hanzo/gui");
|
|
16
18
|
const slot_1 = require("../backends/gui/slot.cjs");
|
|
17
|
-
|
|
19
|
+
/** Card width, px. Fixed, so a strip scans as a row rather than ragged columns. */
|
|
20
|
+
const CARD = 168;
|
|
21
|
+
function Sources({ sources, title = 'Sources', onOpen, ...props }) {
|
|
18
22
|
if (sources.length === 0)
|
|
19
23
|
return null;
|
|
20
|
-
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('sources'), gap: "$2",
|
|
24
|
+
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
25
|
}
|
|
22
|
-
function
|
|
26
|
+
function SourceCard({ source, index, onOpen, ...props }) {
|
|
23
27
|
const press = onOpen ? () => onOpen(source) : undefined;
|
|
24
|
-
|
|
28
|
+
const label = source.host ?? source.title;
|
|
29
|
+
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
30
|
}
|
package/dist/chat/Sources.d.ts
CHANGED
|
@@ -1,23 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Sources — the citations for a turn, as a strip of cards.
|
|
3
|
+
*
|
|
4
|
+
* Each card leads with the host, which is what a reader scans to decide whether
|
|
5
|
+
* they trust a source; the title is the tiebreaker under it. The strip scrolls
|
|
6
|
+
* sideways so it stays one row tall at any count.
|
|
7
|
+
*
|
|
8
|
+
* The number matches a marker in the prose. Minting that marker belongs to the
|
|
9
|
+
* markdown pipeline, which stays with the surface.
|
|
10
|
+
*/
|
|
11
|
+
import { YStack } from '@hanzo/gui';
|
|
12
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
13
|
export interface Source {
|
|
3
14
|
id: string;
|
|
4
15
|
/** Accessible name and tooltip — a title, repo or file path. */
|
|
5
16
|
title: string;
|
|
6
17
|
/** Opened on press. Surfaces without navigation can omit it. */
|
|
7
18
|
href?: string;
|
|
8
|
-
/** Favicon or mark. Falls back to the first letter of `title`. */
|
|
19
|
+
/** Favicon or mark. Falls back to the first letter of `host` or `title`. */
|
|
9
20
|
icon?: ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Who published it — `nytimes.com`, a repo, a filename.
|
|
23
|
+
*
|
|
24
|
+
* Derived by the surface: a `new URL()` here would be wrong for a source that
|
|
25
|
+
* is a file path rather than a link.
|
|
26
|
+
*/
|
|
27
|
+
host?: string;
|
|
10
28
|
}
|
|
11
|
-
export interface SourcesProps {
|
|
29
|
+
export interface SourcesProps extends Omit<ComponentProps<typeof YStack>, 'children'> {
|
|
12
30
|
sources: Source[];
|
|
13
31
|
title?: string;
|
|
14
32
|
/** Raised on press. Given `href`, a surface may navigate instead. */
|
|
15
33
|
onOpen?: (source: Source) => void;
|
|
16
34
|
}
|
|
17
|
-
export declare function Sources({ sources, title, onOpen }: SourcesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
18
|
-
export interface
|
|
35
|
+
export declare function Sources({ sources, title, onOpen, ...props }: SourcesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
36
|
+
export interface SourceCardProps extends Omit<ComponentProps<typeof YStack>, 'children' | 'role'> {
|
|
19
37
|
source: Source;
|
|
38
|
+
/** Position in the list, 1-based — the number the prose's marker refers to. */
|
|
39
|
+
index?: number;
|
|
20
40
|
onOpen?: (source: Source) => void;
|
|
21
41
|
}
|
|
22
|
-
export declare function
|
|
42
|
+
export declare function SourceCard({ source, index, onOpen, ...props }: SourceCardProps): import("react/jsx-runtime").JSX.Element;
|
|
23
43
|
//# 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;;;;;;;;;GASG;AACH,OAAO,EAAuB,MAAM,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAOtD,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;;;;;OAKG;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,kDA6BrF;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,2CA2D9E"}
|
package/dist/chat/Sources.js
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
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
|
+
* Each card leads with the host, which is what a reader scans to decide whether
|
|
7
|
+
* they trust a source; the title is the tiebreaker under it. The strip scrolls
|
|
8
|
+
* sideways so it stays one row tall at any count.
|
|
9
|
+
*
|
|
10
|
+
* The number matches a marker in the prose. Minting that marker belongs to the
|
|
11
|
+
* markdown pipeline, which stays with the surface.
|
|
10
12
|
*/
|
|
11
13
|
import { SizableText, XStack, YStack } from '@hanzo/gui';
|
|
12
14
|
import { slot, tip } from '../backends/gui/slot.js';
|
|
13
|
-
|
|
15
|
+
/** Card width, px. Fixed, so a strip scans as a row rather than ragged columns. */
|
|
16
|
+
const CARD = 168;
|
|
17
|
+
export function Sources({ sources, title = 'Sources', onOpen, ...props }) {
|
|
14
18
|
if (sources.length === 0)
|
|
15
19
|
return null;
|
|
16
|
-
return (_jsxs(YStack, { ...slot('sources'), gap: "$2",
|
|
20
|
+
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
21
|
}
|
|
18
|
-
export function
|
|
22
|
+
export function SourceCard({ source, index, onOpen, ...props }) {
|
|
19
23
|
const press = onOpen ? () => onOpen(source) : undefined;
|
|
20
|
-
|
|
24
|
+
const label = source.host ?? source.title;
|
|
25
|
+
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
26
|
}
|
|
22
27
|
//# 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":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;GASG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGxD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAEhD,mFAAmF;AACnF,MAAM,IAAI,GAAG,GAAG,CAAA;AA0BhB,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,EAAgB;IACpF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAErC,OAAO,CACL,MAAC,MAAM,OAAK,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAC,IAAI,KAAK,KAAK,aAC7C,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,EAIT,KAAC,MAAM,OACD,IAAI,CAAC,eAAe,CAAC,EACzB,QAAQ,EAAC,QAAQ,EACjB,OAAO,EAAC,SAAS,EACjB,GAAG,EAAC,IAAI,EACR,EAAE,EAAC,IAAI,YAEN,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAC1B,KAAC,UAAU,IAAiB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,IAAvD,MAAM,CAAC,EAAE,CAAkD,CAC7E,CAAC,GACK,IACF,CACV,CAAA;AACH,CAAC;AASD,MAAM,UAAU,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,EAAmB;IAC7E,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAA;IAEzC,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,aAAa,CAAC,EACvB,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,CAAC,EACT,GAAG,EAAC,MAAM,EACV,CAAC,EAAC,MAAM,EACR,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,EAAE,EAAC,SAAS,EACZ,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,gBAEnB,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,KAC7C,KAAK,aAET,MAAC,MAAM,IAAC,KAAK,EAAC,QAAQ,EAAC,GAAG,EAAC,MAAM,aAC9B,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CACf,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,SAAS,YACnC,KAAK,GACM,CACf,CAAC,CAAC,CAAC,IAAI,EACR,KAAC,MAAM,IACL,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,MAAM,EAAE,CAAC,EACT,KAAK,EAAC,QAAQ,EACd,OAAO,EAAC,QAAQ,EAChB,OAAO,EAAC,IAAI,EACZ,QAAQ,EAAC,QAAQ,EACjB,EAAE,EAAC,SAAS,YAEX,MAAM,CAAC,IAAI,IAAI,CACd,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,UAAU,YACpC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAClB,CACf,GACM,EACT,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,UAAU,EAAC,aAAa,EAAE,CAAC,YACrD,KAAK,GACM,IACP,EAGT,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,UAAU,EAAC,aAAa,EAAE,CAAC,YACrD,MAAM,CAAC,KAAK,GACD,IACP,CACV,CAAA;AACH,CAAC"}
|