@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.
Files changed (81) hide show
  1. package/dist/backends/gui/textarea.cjs +5 -10
  2. package/dist/backends/gui/textarea.d.ts +11 -32
  3. package/dist/backends/gui/textarea.d.ts.map +1 -1
  4. package/dist/backends/gui/textarea.js +5 -10
  5. package/dist/backends/gui/textarea.js.map +1 -1
  6. package/dist/chat/Code.cjs +2 -2
  7. package/dist/chat/Code.d.ts +16 -3
  8. package/dist/chat/Code.d.ts.map +1 -1
  9. package/dist/chat/Code.js +2 -2
  10. package/dist/chat/Code.js.map +1 -1
  11. package/dist/chat/Composer.cjs +17 -47
  12. package/dist/chat/Composer.d.ts +40 -3
  13. package/dist/chat/Composer.d.ts.map +1 -1
  14. package/dist/chat/Composer.js +17 -47
  15. package/dist/chat/Composer.js.map +1 -1
  16. package/dist/chat/Failure.cjs +11 -30
  17. package/dist/chat/Failure.d.ts +15 -3
  18. package/dist/chat/Failure.d.ts.map +1 -1
  19. package/dist/chat/Failure.js +11 -30
  20. package/dist/chat/Failure.js.map +1 -1
  21. package/dist/chat/Header.cjs +2 -2
  22. package/dist/chat/Header.d.ts +20 -3
  23. package/dist/chat/Header.d.ts.map +1 -1
  24. package/dist/chat/Header.js +2 -2
  25. package/dist/chat/Header.js.map +1 -1
  26. package/dist/chat/Message.cjs +16 -33
  27. package/dist/chat/Message.d.ts +26 -15
  28. package/dist/chat/Message.d.ts.map +1 -1
  29. package/dist/chat/Message.js +16 -33
  30. package/dist/chat/Message.js.map +1 -1
  31. package/dist/chat/Sources.cjs +15 -10
  32. package/dist/chat/Sources.d.ts +26 -6
  33. package/dist/chat/Sources.d.ts.map +1 -1
  34. package/dist/chat/Sources.js +14 -9
  35. package/dist/chat/Sources.js.map +1 -1
  36. package/dist/chat/Step.cjs +18 -44
  37. package/dist/chat/Step.d.ts +9 -20
  38. package/dist/chat/Step.d.ts.map +1 -1
  39. package/dist/chat/Step.js +18 -44
  40. package/dist/chat/Step.js.map +1 -1
  41. package/dist/chat/Thread.cjs +19 -17
  42. package/dist/chat/Thread.d.ts +25 -3
  43. package/dist/chat/Thread.d.ts.map +1 -1
  44. package/dist/chat/Thread.js +19 -17
  45. package/dist/chat/Thread.js.map +1 -1
  46. package/dist/chat/index.cjs +22 -46
  47. package/dist/chat/index.d.ts +21 -45
  48. package/dist/chat/index.d.ts.map +1 -1
  49. package/dist/chat/index.js +21 -45
  50. package/dist/chat/index.js.map +1 -1
  51. package/dist/chat/pure.cjs +22 -0
  52. package/dist/chat/pure.d.ts +3 -0
  53. package/dist/chat/pure.d.ts.map +1 -0
  54. package/dist/chat/pure.js +16 -0
  55. package/dist/chat/pure.js.map +1 -0
  56. package/dist/chat/send.cjs +12 -13
  57. package/dist/chat/send.d.ts +8 -6
  58. package/dist/chat/send.d.ts.map +1 -1
  59. package/dist/chat/send.js +12 -13
  60. package/dist/chat/send.js.map +1 -1
  61. package/dist/chat/stick.cjs +3 -5
  62. package/dist/chat/stick.d.ts +2 -4
  63. package/dist/chat/stick.d.ts.map +1 -1
  64. package/dist/chat/stick.js +3 -5
  65. package/dist/chat/stick.js.map +1 -1
  66. package/dist/gallery.cjs +5 -4
  67. package/dist/gallery.d.ts.map +1 -1
  68. package/dist/gallery.js +5 -4
  69. package/dist/gallery.js.map +1 -1
  70. package/dist/product/CopyButton.cjs +2 -2
  71. package/dist/product/CopyButton.d.ts +6 -2
  72. package/dist/product/CopyButton.d.ts.map +1 -1
  73. package/dist/product/CopyButton.js +2 -2
  74. package/dist/product/CopyButton.js.map +1 -1
  75. package/dist/product/pure.cjs +10 -1
  76. package/dist/product/pure.d.ts +2 -0
  77. package/dist/product/pure.d.ts.map +1 -1
  78. package/dist/product/pure.js +5 -0
  79. package/dist/product/pure.js.map +1 -1
  80. package/dist/styles.css +14 -2
  81. package/package.json +7 -1
@@ -7,51 +7,29 @@ const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  * Step — something the assistant did on the way to the answer, and how it went.
8
8
  *
9
9
  * A tool call, a retrieval, a plan, a stretch of reasoning, a progress report:
10
- * every one of them is a named region that reports a state and opens to show
11
- * its detail. Two repos had written that arrangement NINE times without ever
12
- * naming it — hanzo/chat once (`ToolCall.tsx` + `ProgressText.tsx`), hanzo.app
13
- * eight (`chat-panel/index.tsx` `ToolDisplay`, `SyntheticErrorDisplay`,
14
- * `ReasoningDisplay`, `PlanDisplay`, `AgentDisplay`, `ProgressDisplay`, the
15
- * inline `project_context` block, and the builder's own `CollapsibleSection` in
16
- * `ask-ai/chat-thread.tsx:330`). Nine chances to order the header differently,
17
- * and they took most of them.
10
+ * each is a named region that reports a state and opens to show its detail.
11
+ * The header, the state mark, the disclosure and the frame are here; what goes
12
+ * inside is `children`.
18
13
  *
19
- * What goes INSIDE stays the surface's: chat renders the input as a code block
20
- * and the result through its own markdown, the app renders
21
- * `JSON.stringify(parameters, null, 2)`. That is `children`. The header, the
22
- * state mark, the disclosure and the frame are the same drawing in all nine and
23
- * they are here.
14
+ * Open/closed is `Collapsible`, so `aria-expanded`, `aria-controls` and the
15
+ * keyboard come from the primitive.
24
16
  *
25
- * The open/closed behaviour is `Collapsible`, not a hand-rolled height
26
- * animation. Both existing implementations rolled their own — chat measures
27
- * `scrollHeight` in a `useLayoutEffect`, keeps a `ResizeObserver` alive and
28
- * transitions an explicit pixel height — and that is the keyboard handling and
29
- * the `aria-expanded`/`aria-controls` pair re-derived by hand each time. The
30
- * primitive already has them.
31
- *
32
- * There is no duration and no elapsed time. Neither implementation shows one,
33
- * and chat's apparent progress is not measured at all: `useProgress.ts:54`
34
- * ticks a `setInterval` by 0.007 every 200ms and caps at 0.95 until the server
35
- * says otherwise. A number that is invented should not be given a place to
36
- * render.
17
+ * No duration: nothing upstream measures one, and a progress ratio ticked by a
18
+ * timer is not a measurement.
37
19
  */
38
20
  const gui_1 = require("@hanzo/gui");
39
21
  const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
40
22
  const gui_2 = require("../backends/gui/index.cjs");
41
23
  const slot_1 = require("../backends/gui/slot.cjs");
42
- /** Edge of the state mark, px. One size, so the header never reflows on a state
43
- * change — a step that finishes must not move the text beside it. */
24
+ /** Edge of the state mark, px. One size, so a state change never reflows the
25
+ * header. */
44
26
  const MARK = 13;
45
27
  /**
46
28
  * The mark for each state. `running` is the one that moves.
47
29
  *
48
- * Tinted on the glyph, never on the box: `XStack` is a View and has no `color`,
49
- * so a colour set there type-errors rather than cascading — which is this
50
- * package's "a prop must actually arrive" rule catching a habit borrowed from
51
- * the DOM. Written as four call sites rather than a lookup table because the
52
- * Spinner and the three glyphs do not share a props type: the icons take a
53
- * themed `GetThemeValueForKey<'color'>` and the Spinner takes a plain string,
54
- * and the table that unified them only typechecked by widening both to `any`.
30
+ * Tinted on the glyph: `XStack` is a View and takes no `color`. Four call sites
31
+ * rather than a table because the Spinner and the icons do not share a props
32
+ * type — the icons take a themed colour, the Spinner a plain string.
55
33
  */
56
34
  const mark = (status) => {
57
35
  switch (status) {
@@ -65,17 +43,13 @@ const mark = (status) => {
65
43
  return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Ban, { size: MARK, color: "$color11" });
66
44
  }
67
45
  };
68
- function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, }) {
69
- // A step with no body is a statement, not a control. Rendering a dead chevron
70
- // and a focusable trigger over nothing is how a keyboard user is sent to a
71
- // stop that does not answer.
46
+ function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, ...props }) {
47
+ // A step with no body is a statement, not a control: no chevron, no trigger,
48
+ // no keyboard stop that does not answer.
72
49
  const opens = children != null;
73
50
  const header = ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2", px: "$3", py: "$2", width: "100%", children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { width: MARK + 1, items: "center", justify: "center", shrink: 0, children: mark(status) }), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color12", numberOfLines: 1, children: name }), detail ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$color10", numberOfLines: 1, shrink: 1, children: detail })) : null, (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1 }), opens ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 13, color: "$color10" }) : null] }));
74
51
  return ((0, jsx_runtime_1.jsxs)(gui_2.Collapsible, { ...(0, slot_1.slot)('step'), "data-status": status, open: open, defaultOpen: defaultOpen, onOpenChange: onOpenChange, width: "100%", rounded: "$4", borderWidth: 1,
75
- // The failure edge, not a red one. `product/tone.ts` states the rule this
76
- // package works under — "this system has no colour to spend" — and marks
77
- // its `stopped` register with a border rather than a fill. A step that
78
- // errored is set apart the same way, so it still reads as a failure in a
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] }));
52
+ // An edge, not a red fill — `product/tone.ts` marks `stopped` the same
53
+ // way, so it survives a brand that retunes the ramp.
54
+ 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
55
  }
@@ -1,34 +1,23 @@
1
- import type { ReactNode } from 'react';
2
- /**
3
- * How a step went.
4
- *
5
- * Four, from the union of what the two implementations track. chat reports
6
- * `error`, `cancelled` and a progress ratio it treats as running-or-done
7
- * (`ToolCall.tsx:139`); the app reports `pending | executing | completed |
8
- * failed` (`chat-panel/index.tsx:97`) — and `pending` and `executing` draw the
9
- * same thing, because from the reader's side a step that has not started and a
10
- * step that is running are both "not yet".
11
- */
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+ import { Collapsible } from '../backends/gui/index.js';
3
+ /** How a step went. A step that has not started and one that is running draw
4
+ * the same thing: from the reader's side both are "not yet". */
12
5
  export type Ran = 'running' | 'done' | 'error' | 'cancelled';
13
- export interface StepProps {
6
+ export interface StepProps extends Omit<ComponentProps<typeof Collapsible>, 'children' | 'open' | 'defaultOpen' | 'onOpenChange'> {
14
7
  /** What ran — a tool name, "Reasoning", "Plan". */
15
8
  name: string;
16
9
  status?: Ran;
17
- /**
18
- * One line beside the name: the command, the path, the query. Clamped to a
19
- * single line — the app truncates its own to 50 characters
20
- * (`chat-panel/index.tsx:1148`) precisely because an untruncated one wraps
21
- * the header and moves the chevron.
22
- */
10
+ /** One line beside the name: the command, the path, the query. Clamped, or it
11
+ * wraps the header and moves the chevron. */
23
12
  detail?: string;
24
13
  /** Revealed when open. Omit it and the step has nothing to open, so it does
25
14
  * not offer to: no chevron, no trigger, no keyboard stop. */
26
15
  children?: ReactNode;
27
16
  /** Uncontrolled. */
28
17
  defaultOpen?: boolean;
29
- /** Controlled — the app holds every step's state in one `Set` on the panel. */
18
+ /** Controlled. */
30
19
  open?: boolean;
31
20
  onOpenChange?: (open: boolean) => void;
32
21
  }
33
- export declare function Step({ name, status, detail, children, defaultOpen, open, onOpenChange, }: StepProps): import("react/jsx-runtime").JSX.Element;
22
+ export declare function Step({ name, status, detail, children, defaultOpen, open, onOpenChange, ...props }: StepProps): import("react/jsx-runtime").JSX.Element;
34
23
  //# sourceMappingURL=Step.d.ts.map
@@ -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;AAKtC;;;;;;;;;GASG;AACH,MAAM,MAAM,GAAG,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CAAA;AA8B5D,MAAM,WAAW,SAAS;IACxB,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,GACb,EAAE,SAAS,2CA4DX"}
1
+ {"version":3,"file":"Step.d.ts","sourceRoot":"","sources":["../../src/chat/Step.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,WAAW,EAAmD,MAAM,iBAAiB,CAAA;AAG9F;iEACiE;AACjE,MAAM,MAAM,GAAG,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CAAA;AA0B5D,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;kDAC8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;kEAC8D;IAC9D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,oBAAoB;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,kBAAkB;IAClB,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,2CAyDX"}
package/dist/chat/Step.js CHANGED
@@ -4,51 +4,29 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  * Step — something the assistant did on the way to the answer, and how it went.
5
5
  *
6
6
  * A tool call, a retrieval, a plan, a stretch of reasoning, a progress report:
7
- * every one of them is a named region that reports a state and opens to show
8
- * its detail. Two repos had written that arrangement NINE times without ever
9
- * naming it — hanzo/chat once (`ToolCall.tsx` + `ProgressText.tsx`), hanzo.app
10
- * eight (`chat-panel/index.tsx` `ToolDisplay`, `SyntheticErrorDisplay`,
11
- * `ReasoningDisplay`, `PlanDisplay`, `AgentDisplay`, `ProgressDisplay`, the
12
- * inline `project_context` block, and the builder's own `CollapsibleSection` in
13
- * `ask-ai/chat-thread.tsx:330`). Nine chances to order the header differently,
14
- * and they took most of them.
7
+ * each is a named region that reports a state and opens to show its detail.
8
+ * The header, the state mark, the disclosure and the frame are here; what goes
9
+ * inside is `children`.
15
10
  *
16
- * What goes INSIDE stays the surface's: chat renders the input as a code block
17
- * and the result through its own markdown, the app renders
18
- * `JSON.stringify(parameters, null, 2)`. That is `children`. The header, the
19
- * state mark, the disclosure and the frame are the same drawing in all nine and
20
- * they are here.
11
+ * Open/closed is `Collapsible`, so `aria-expanded`, `aria-controls` and the
12
+ * keyboard come from the primitive.
21
13
  *
22
- * The open/closed behaviour is `Collapsible`, not a hand-rolled height
23
- * animation. Both existing implementations rolled their own — chat measures
24
- * `scrollHeight` in a `useLayoutEffect`, keeps a `ResizeObserver` alive and
25
- * transitions an explicit pixel height — and that is the keyboard handling and
26
- * the `aria-expanded`/`aria-controls` pair re-derived by hand each time. The
27
- * primitive already has them.
28
- *
29
- * There is no duration and no elapsed time. Neither implementation shows one,
30
- * and chat's apparent progress is not measured at all: `useProgress.ts:54`
31
- * ticks a `setInterval` by 0.007 every 200ms and caps at 0.95 until the server
32
- * says otherwise. A number that is invented should not be given a place to
33
- * render.
14
+ * No duration: nothing upstream measures one, and a progress ratio ticked by a
15
+ * timer is not a measurement.
34
16
  */
35
17
  import { SizableText, XStack, YStack } from '@hanzo/gui';
36
18
  import { Ban, Check, ChevronDown, TriangleAlert } from '@hanzogui/lucide-icons-2';
37
19
  import { Collapsible, CollapsibleContent, CollapsibleTrigger, Spinner } from '../backends/gui/index.js';
38
20
  import { slot } from '../backends/gui/slot.js';
39
- /** Edge of the state mark, px. One size, so the header never reflows on a state
40
- * change — a step that finishes must not move the text beside it. */
21
+ /** Edge of the state mark, px. One size, so a state change never reflows the
22
+ * header. */
41
23
  const MARK = 13;
42
24
  /**
43
25
  * The mark for each state. `running` is the one that moves.
44
26
  *
45
- * Tinted on the glyph, never on the box: `XStack` is a View and has no `color`,
46
- * so a colour set there type-errors rather than cascading — which is this
47
- * package's "a prop must actually arrive" rule catching a habit borrowed from
48
- * the DOM. Written as four call sites rather than a lookup table because the
49
- * Spinner and the three glyphs do not share a props type: the icons take a
50
- * themed `GetThemeValueForKey<'color'>` and the Spinner takes a plain string,
51
- * and the table that unified them only typechecked by widening both to `any`.
27
+ * Tinted on the glyph: `XStack` is a View and takes no `color`. Four call sites
28
+ * rather than a table because the Spinner and the icons do not share a props
29
+ * type — the icons take a themed colour, the Spinner a plain string.
52
30
  */
53
31
  const mark = (status) => {
54
32
  switch (status) {
@@ -62,18 +40,14 @@ const mark = (status) => {
62
40
  return _jsx(Ban, { size: MARK, color: "$color11" });
63
41
  }
64
42
  };
65
- export function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, }) {
66
- // A step with no body is a statement, not a control. Rendering a dead chevron
67
- // and a focusable trigger over nothing is how a keyboard user is sent to a
68
- // stop that does not answer.
43
+ export function Step({ name, status = 'done', detail, children, defaultOpen, open, onOpenChange, ...props }) {
44
+ // A step with no body is a statement, not a control: no chevron, no trigger,
45
+ // no keyboard stop that does not answer.
69
46
  const opens = children != null;
70
47
  const header = (_jsxs(XStack, { items: "center", gap: "$2", px: "$3", py: "$2", width: "100%", children: [_jsx(XStack, { width: MARK + 1, items: "center", justify: "center", shrink: 0, children: mark(status) }), _jsx(SizableText, { size: "$1", color: "$color12", numberOfLines: 1, children: name }), detail ? (_jsx(SizableText, { size: "$1", color: "$color10", numberOfLines: 1, shrink: 1, children: detail })) : null, _jsx(XStack, { flex: 1 }), opens ? _jsx(ChevronDown, { size: 13, color: "$color10" }) : null] }));
71
48
  return (_jsxs(Collapsible, { ...slot('step'), "data-status": status, open: open, defaultOpen: defaultOpen, onOpenChange: onOpenChange, width: "100%", rounded: "$4", borderWidth: 1,
72
- // The failure edge, not a red one. `product/tone.ts` states the rule this
73
- // package works under — "this system has no colour to spend" — and marks
74
- // its `stopped` register with a border rather than a fill. A step that
75
- // errored is set apart the same way, so it still reads as a failure in a
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] }));
49
+ // An edge, not a red fill — `product/tone.ts` marks `stopped` the same
50
+ // way, so it survives a brand that retunes the ramp.
51
+ 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
52
  }
79
53
  //# sourceMappingURL=Step.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Step.js","sourceRoot":"","sources":["../../src/chat/Step.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Step.js","sourceRoot":"","sources":["../../src/chat/Step.tsx"],"names":[],"mappings":"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"}
@@ -1,15 +1,14 @@
1
1
  'use client';"use strict";
2
2
  'use client';
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.Thread = 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.
8
8
  *
9
- * It does the one thing every surface had re-solved: follow a streaming answer
10
- * to the bottom, and stop following the instant the reader scrolls up. The
11
- * decision is `pinned()`, asserted without a DOM; this component only wires it
12
- * to the platform's scroll view, so momentum and keyboard stay the host's.
9
+ * Follows a streaming answer to the bottom and stops the moment the reader
10
+ * scrolls up. The decision is `pinned()`; this only wires it to the platform's
11
+ * scroll view, so momentum and keyboard stay the host's.
13
12
  */
14
13
  const gui_1 = require("@hanzo/gui");
15
14
  const react_1 = require("react");
@@ -17,26 +16,29 @@ const slot_1 = require("../backends/gui/slot.cjs");
17
16
  const stick_1 = require("./stick.cjs");
18
17
  /** Reading-measure cap for prose, in px. */
19
18
  const MEASURE = 768;
20
- function Thread({ children, maxWidth = MEASURE, slack = stick_1.SLACK, gap = 24 }) {
19
+ exports.Thread = (0, react_1.forwardRef)(function Thread({ children, maxWidth = MEASURE, slack = stick_1.SLACK, gap = 24, onScroll, column, ...props }, ref) {
21
20
  const view = (0, react_1.useRef)(null);
22
- const track = (0, react_1.useRef)({ offset: 0, viewport: 0, content: 0 });
23
21
  const follow = (0, react_1.useRef)(true);
22
+ // Ours to scroll with, and the caller's.
23
+ const hold = (0, react_1.useCallback)((el) => {
24
+ view.current = el;
25
+ if (typeof ref === 'function')
26
+ ref(el);
27
+ else if (ref)
28
+ ref.current = el;
29
+ }, [ref]);
24
30
  const grew = (0, react_1.useCallback)(() => {
25
31
  if (follow.current)
26
32
  view.current?.scrollToEnd({ animated: false });
27
33
  }, []);
28
- return ((0, jsx_runtime_1.jsx)(gui_1.ScrollView, { ref: view, ...(0, slot_1.slot)('thread'), flex: 1, width: "100%", scrollEventThrottle: 16, onLayout: (e) => {
29
- track.current = { ...track.current, viewport: e.nativeEvent.layout.height };
30
- }, onContentSizeChange: (_w, h) => {
31
- track.current = { ...track.current, content: h };
32
- grew();
33
- }, onScroll: (e) => {
34
+ 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
35
  const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent;
35
- track.current = {
36
+ const track = {
36
37
  offset: contentOffset.y,
37
38
  viewport: layoutMeasurement.height,
38
39
  content: contentSize.height,
39
40
  };
40
- follow.current = (0, stick_1.pinned)(track.current, slack);
41
- }, children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('thread-column'), width: "100%", gap: gap, py: gap, ...(maxWidth ? { maxW: maxWidth, self: 'center', px: '$3' } : null), children: children }) }));
42
- }
41
+ follow.current = (0, stick_1.pinned)(track, slack);
42
+ onScroll?.(e, { pinned: follow.current, track });
43
+ }, ...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 }) }));
44
+ });
@@ -1,11 +1,33 @@
1
- import { type ReactNode } from 'react';
2
- export interface ThreadProps {
1
+ /**
2
+ * Thread — the scrolling column of turns.
3
+ *
4
+ * Follows a streaming answer to the bottom and stops the moment the reader
5
+ * scrolls up. The decision is `pinned()`; this only wires it to the platform's
6
+ * scroll view, so momentum and keyboard stay the host's.
7
+ */
8
+ import { ScrollView, YStack, type GetRef } from '@hanzo/gui';
9
+ import { type ComponentProps, type ReactNode } from 'react';
10
+ import { type Track } from './stick.js';
11
+ type Scroller = GetRef<typeof ScrollView> & {
12
+ scrollToEnd(o: {
13
+ animated: boolean;
14
+ }): void;
15
+ };
16
+ export interface ThreadProps extends Omit<ComponentProps<typeof ScrollView>, 'children' | 'onScroll'> {
3
17
  children?: ReactNode;
4
18
  /** Reading-measure cap. Pass `0` to fill the container. */
5
19
  maxWidth?: number;
6
20
  /** How near the end still counts as "at the bottom", in px. */
7
21
  slack?: number;
8
22
  gap?: number;
23
+ /** The scroll, with the follow decision and the numbers it was made from. */
24
+ onScroll?: (event: unknown, at: {
25
+ pinned: boolean;
26
+ track: Track;
27
+ }) => void;
28
+ /** The column that holds the turns, for a surface that needs to reach it. */
29
+ column?: Omit<ComponentProps<typeof YStack>, 'children'>;
9
30
  }
10
- export declare function Thread({ children, maxWidth, slack, gap }: ThreadProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare const Thread: import("react").ForwardRefExoticComponent<Omit<ThreadProps, "ref"> & import("react").RefAttributes<Scroller>>;
32
+ export {};
11
33
  //# sourceMappingURL=Thread.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Thread.d.ts","sourceRoot":"","sources":["../../src/chat/Thread.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAQ3D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAkB,EAAE,KAAa,EAAE,GAAQ,EAAE,EAAE,WAAW,2CA+C5F"}
1
+ {"version":3,"file":"Thread.d.ts","sourceRoot":"","sources":["../../src/chat/Thread.tsx"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAA;AAC5D,OAAO,EAAmC,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAG5F,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAKnD,KAAK,QAAQ,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,GAAG;IAAE,WAAW,CAAC,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAA;CAAE,CAAA;AAE3F,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,UAAU,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACxE,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,KAAK,IAAI,CAAA;IAC1E,6EAA6E;IAC7E,MAAM,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;CACzD;AAED,eAAO,MAAM,MAAM,+GAqDjB,CAAA"}
@@ -3,38 +3,40 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  /**
4
4
  * Thread — the scrolling column of turns.
5
5
  *
6
- * It does the one thing every surface had re-solved: follow a streaming answer
7
- * to the bottom, and stop following the instant the reader scrolls up. The
8
- * decision is `pinned()`, asserted without a DOM; this component only wires it
9
- * to the platform's scroll view, so momentum and keyboard stay the host's.
6
+ * Follows a streaming answer to the bottom and stops the moment the reader
7
+ * scrolls up. The decision is `pinned()`; this only wires it to the platform's
8
+ * scroll view, so momentum and keyboard stay the host's.
10
9
  */
11
10
  import { ScrollView, YStack } from '@hanzo/gui';
12
- import { useCallback, useRef } from 'react';
11
+ import { forwardRef, useCallback, useRef } from 'react';
13
12
  import { slot } from '../backends/gui/slot.js';
14
13
  import { pinned, SLACK } from './stick.js';
15
14
  /** Reading-measure cap for prose, in px. */
16
15
  const MEASURE = 768;
17
- export function Thread({ children, maxWidth = MEASURE, slack = SLACK, gap = 24 }) {
16
+ export const Thread = /* @__PURE__ */ forwardRef(function Thread({ children, maxWidth = MEASURE, slack = SLACK, gap = 24, onScroll, column, ...props }, ref) {
18
17
  const view = useRef(null);
19
- const track = useRef({ offset: 0, viewport: 0, content: 0 });
20
18
  const follow = useRef(true);
19
+ // Ours to scroll with, and the caller's.
20
+ const hold = useCallback((el) => {
21
+ view.current = el;
22
+ if (typeof ref === 'function')
23
+ ref(el);
24
+ else if (ref)
25
+ ref.current = el;
26
+ }, [ref]);
21
27
  const grew = useCallback(() => {
22
28
  if (follow.current)
23
29
  view.current?.scrollToEnd({ animated: false });
24
30
  }, []);
25
- return (_jsx(ScrollView, { ref: view, ...slot('thread'), flex: 1, width: "100%", scrollEventThrottle: 16, onLayout: (e) => {
26
- track.current = { ...track.current, viewport: e.nativeEvent.layout.height };
27
- }, onContentSizeChange: (_w, h) => {
28
- track.current = { ...track.current, content: h };
29
- grew();
30
- }, onScroll: (e) => {
31
+ return (_jsx(ScrollView, { ref: hold, ...slot('thread'), flex: 1, width: "100%", scrollEventThrottle: 16, onContentSizeChange: grew, onScroll: (e) => {
31
32
  const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent;
32
- track.current = {
33
+ const track = {
33
34
  offset: contentOffset.y,
34
35
  viewport: layoutMeasurement.height,
35
36
  content: contentSize.height,
36
37
  };
37
- follow.current = pinned(track.current, slack);
38
- }, children: _jsx(YStack, { ...slot('thread-column'), width: "100%", gap: gap, py: gap, ...(maxWidth ? { maxW: maxWidth, self: 'center', px: '$3' } : null), children: children }) }));
39
- }
38
+ follow.current = pinned(track, slack);
39
+ onScroll?.(e, { pinned: follow.current, track });
40
+ }, ...props, children: _jsx(YStack, { ...slot('thread-column'), width: "100%", gap: gap, py: gap, ...(maxWidth ? { maxW: maxWidth, self: 'center', px: '$3' } : null), ...column, children: children }) }));
41
+ });
40
42
  //# sourceMappingURL=Thread.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Thread.js","sourceRoot":"","sources":["../../src/chat/Thread.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAe,MAAM,YAAY,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAA;AAE3D,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,4CAA4C;AAC5C,MAAM,OAAO,GAAG,GAAG,CAAA;AAWnB,MAAM,UAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,GAAG,EAAE,EAAe;IAC3F,MAAM,IAAI,GAAG,MAAM,CAGjB,IAAI,CAAC,CAAA;IACP,MAAM,KAAK,GAAG,MAAM,CAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;IACnE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IAE3B,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,IAAI,MAAM,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;IACpE,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,KAAC,UAAU,IACT,GAAG,EAAE,IAAI,KACL,IAAI,CAAC,QAAQ,CAAC,EAClB,IAAI,EAAE,CAAC,EACP,KAAK,EAAC,MAAM,EACZ,mBAAmB,EAAE,EAAE,EACvB,QAAQ,EAAE,CAAC,CAAM,EAAE,EAAE;YACnB,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;QAC7E,CAAC,EACD,mBAAmB,EAAE,CAAC,EAAO,EAAE,CAAM,EAAE,EAAE;YACvC,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;YAChD,IAAI,EAAE,CAAA;QACR,CAAC,EACD,QAAQ,EAAE,CAAC,CAAM,EAAE,EAAE;YACnB,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,WAAW,CAAA;YACvE,KAAK,CAAC,OAAO,GAAG;gBACd,MAAM,EAAE,aAAa,CAAC,CAAC;gBACvB,QAAQ,EAAE,iBAAiB,CAAC,MAAM;gBAClC,OAAO,EAAE,WAAW,CAAC,MAAM;aAC5B,CAAA;YACD,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC/C,CAAC,YAED,KAAC,MAAM,OACD,IAAI,CAAC,eAAe,CAAC,EACzB,KAAK,EAAC,MAAM,EACZ,GAAG,EAAE,GAAG,EACR,EAAE,EAAE,GAAG,KACH,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAE5E,QAAQ,GACF,GACE,CACd,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Thread.js","sourceRoot":"","sources":["../../src/chat/Thread.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAe,MAAM,YAAY,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAuC,MAAM,OAAO,CAAA;AAE5F,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,4CAA4C;AAC5C,MAAM,OAAO,GAAG,GAAG,CAAA;AAkBnB,MAAM,CAAC,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAwB,SAAS,MAAM,CACrF,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,GAAG,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,EACrF,GAAG;IAEH,MAAM,IAAI,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;IAE3B,yCAAyC;IACzC,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,EAAmB,EAAE,EAAE;QACtB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACjB,IAAI,OAAO,GAAG,KAAK,UAAU;YAAE,GAAG,CAAC,EAAE,CAAC,CAAA;aACjC,IAAI,GAAG;YAAG,GAA+C,CAAC,OAAO,GAAG,EAAE,CAAA;IAC7E,CAAC,EACD,CAAC,GAAG,CAAC,CACN,CAAA;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,IAAI,MAAM,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;IACpE,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,CACL,KAAC,UAAU,IACT,GAAG,EAAE,IAAa,KACd,IAAI,CAAC,QAAQ,CAAC,EAClB,IAAI,EAAE,CAAC,EACP,KAAK,EAAC,MAAM,EACZ,mBAAmB,EAAE,EAAE,EACvB,mBAAmB,EAAE,IAAI,EACzB,QAAQ,EAAE,CAAC,CAAM,EAAE,EAAE;YACnB,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,WAAW,CAAA;YACvE,MAAM,KAAK,GAAU;gBACnB,MAAM,EAAE,aAAa,CAAC,CAAC;gBACvB,QAAQ,EAAE,iBAAiB,CAAC,MAAM;gBAClC,OAAO,EAAE,WAAW,CAAC,MAAM;aAC5B,CAAA;YACD,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YACrC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;QAClD,CAAC,KACG,KAAK,YAET,KAAC,MAAM,OACD,IAAI,CAAC,eAAe,CAAC,EACzB,KAAK,EAAC,MAAM,EACZ,GAAG,EAAE,GAAG,EACR,EAAE,EAAE,GAAG,KACH,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAiB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KACzE,MAAM,YAET,QAAQ,GACF,GACE,CACd,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -1,59 +1,35 @@
1
1
  'use client';"use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SourceChip = exports.Sources = exports.Failure = exports.Step = exports.Code = exports.Aside = exports.AsideToggle = exports.ShareButton = exports.HeaderButton = exports.Header = exports.SidebarUser = exports.SidebarFolder = exports.SidebarItem = exports.SidebarSection = exports.SidebarScroll = exports.SidebarNewChat = exports.SidebarIconButton = exports.SidebarHeader = exports.Sidebar = exports.SLACK = exports.pinned = exports.sends = exports.ready = exports.Thread = exports.Message = exports.Caret = exports.ASK = exports.Composer = void 0;
3
+ exports.SourceCard = exports.Sources = exports.Failure = exports.Step = exports.Code = exports.Aside = exports.AsideToggle = exports.ShareButton = exports.HeaderButton = exports.Header = exports.SidebarUser = exports.SidebarFolder = exports.SidebarItem = exports.SidebarSection = exports.SidebarScroll = exports.SidebarNewChat = exports.SidebarIconButton = exports.SidebarHeader = exports.Sidebar = exports.SLACK = exports.pinned = exports.sends = exports.ready = exports.Thread = exports.Message = exports.Caret = exports.ASK = exports.Composer = void 0;
4
4
  /**
5
5
  * @hanzo/ui/chat — the one chat shell, on @hanzo/gui primitives.
6
6
  *
7
- * Shell only: Thread scrolls, Message presents a turn, Composer takes a draft,
8
- * Sidebar navigates between conversations, Header names the current one, and
9
- * Code, Step, Failure and Sources present the pieces of a turn every surface
10
- * renders the same way.
7
+ * Thread scrolls, Message presents a turn, Composer takes a draft, Sidebar
8
+ * navigates between conversations, Header names the current one, and Code,
9
+ * Step, Failure and Sources present the pieces of a turn.
11
10
  *
12
- * This file used to end that sentence with "Content rendering (markdown, tool
13
- * calls) stays with the surface — they disagree on the pipeline, and none of it
14
- * is presentational." Half of that was right and the half that was wrong cost
15
- * nine hand-drawn copies. Re-decided by reading what the three surfaces
16
- * actually render:
11
+ * The markdown pipeline is the surface's and arrives as `children`: the three
12
+ * surfaces run nine plugins, one plugin, and a regex under a bundle ceiling
13
+ * that cannot afford a parser. There is no `renderPart` prop for the same
14
+ * reason — the part union is per-surface too, so a callback here would take a
15
+ * Part type matching nobody's.
17
16
  *
18
- * MARKDOWN STAYS OUT, and not as a preference. hanzo/chat runs seven remark
19
- * plugins and two rehype plugins (`Content/Markdown.tsx:42-65`, including
20
- * katex and highlight.js over a 35-language subset); hanzo.app runs
21
- * remark-gfm and nothing else (`markdown-renderer/index.tsx:107`); the
22
- * extension parses markdown with eighty lines of regex and no dependency at
23
- * all (`answer/markdown.ts`) because `newtab.js` measures 485.9 KB against a
24
- * 500 KB ceiling that fails the build (`scripts/check-bundle-budgets.mjs:29`)
25
- * and its MV3 policy is `script-src 'self'`. Fourteen kilobytes of headroom
26
- * is not a pipeline disagreement to be reconciled; it is a surface that
27
- * cannot afford a parser. So the pipeline is the surface's, and `children` is
28
- * how it arrives — which is also why there is no `renderPart` prop: the part
29
- * UNION is per-surface too (twelve item types in the app's
30
- * `chat-panel/index.tsx` `TurnDisplay`, eight in chat's `Content/Part.tsx`,
31
- * none in the extension), so a callback here would need a Part type that
32
- * matches nobody's. The surface maps its own parts and passes nodes.
17
+ * Everything else about a turn is presentational and lives here: the code
18
+ * frame, the step disclosure, the failure, the streaming caret.
33
19
  *
34
- * THE REST OF IT WAS ALWAYS PRESENTATIONAL. A code block with a language
35
- * label and a copy control, a collapsible step with a state mark, a failure
36
- * with a retry, a streaming caret — every surface draws these and no two draw
37
- * them alike. `Step` alone replaces nine copies across two repos. What is
38
- * inside each of them is still `children`; the frame, the header, the mark
39
- * and the disclosure are here.
20
+ * Props-in, callbacks-out — no transport, no store, no routing. Each component
21
+ * spreads its residual props, and the three that own an inner part publish a
22
+ * way through to it (`Message body`, `Thread column`, `Composer field`).
40
23
  *
41
- * Everything is props-in, callbacks-out: no transport, no store, no routing, no
42
- * active-id resolution. The same components serve a live conversation, a shared
43
- * read-only transcript and a test fixture.
24
+ * `@hanzo/ui/chat/pure` carries `sends`, `ready`, `pinned` and `SLACK` with no
25
+ * imports, for Node and for callers that are not chat.
44
26
  *
45
- * Styling is `$` tokens throughout, never literal colours, so each brand retunes
46
- * through its own theme and nothing here carries a Hanzo mark — which is what
47
- * lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
27
+ * Styling is `$` tokens throughout, never literal colours, so a brand retunes
28
+ * through its own theme and nothing here carries a mark.
48
29
  *
49
- * The model picker is not here: it already ships at `@hanzo/ui/models`, and it
50
- * is not chat-specific.
51
- *
52
- * `CopyButton` is not here either, for the same reason and after the same
53
- * mistake: it lived in `Code.tsx`, so the only way to reach it was
54
- * `@hanzo/ui/chat`, and no one hunting for a copy button looks in a chat module.
55
- * Six surfaces wrote their own instead. It now ships at `@hanzo/ui/product`;
56
- * `Code` imports it from there.
30
+ * The model picker and `CopyButton` are not here — neither is chat-specific, so
31
+ * they ship at `@hanzo/ui/models` and `@hanzo/ui/product`. Nobody hunting for a
32
+ * copy button looks in a chat module.
57
33
  */
58
34
  var Composer_1 = require("./Composer.cjs");
59
35
  Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return Composer_1.Composer; } });
@@ -93,4 +69,4 @@ var Failure_1 = require("./Failure.cjs");
93
69
  Object.defineProperty(exports, "Failure", { enumerable: true, get: function () { return Failure_1.Failure; } });
94
70
  var Sources_1 = require("./Sources.cjs");
95
71
  Object.defineProperty(exports, "Sources", { enumerable: true, get: function () { return Sources_1.Sources; } });
96
- Object.defineProperty(exports, "SourceChip", { enumerable: true, get: function () { return Sources_1.SourceChip; } });
72
+ Object.defineProperty(exports, "SourceCard", { enumerable: true, get: function () { return Sources_1.SourceCard; } });