@hanzo/ui 8.27.3 → 8.27.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.
Files changed (69) hide show
  1. package/dist/backdrop/Backdrop.cjs +420 -0
  2. package/dist/backdrop/Backdrop.d.ts +53 -0
  3. package/dist/backdrop/Backdrop.d.ts.map +1 -0
  4. package/dist/backdrop/Backdrop.js +418 -0
  5. package/dist/backdrop/Backdrop.js.map +1 -0
  6. package/dist/backdrop/index.cjs +50 -0
  7. package/dist/backdrop/index.d.ts +29 -0
  8. package/dist/backdrop/index.d.ts.map +1 -0
  9. package/dist/backdrop/index.js +29 -0
  10. package/dist/backdrop/index.js.map +1 -0
  11. package/dist/backdrop/scene.cjs +439 -0
  12. package/dist/backdrop/scene.d.ts +235 -0
  13. package/dist/backdrop/scene.d.ts.map +1 -0
  14. package/dist/backdrop/scene.js +423 -0
  15. package/dist/backdrop/scene.js.map +1 -0
  16. package/dist/backends/gui/select.cjs +38 -27
  17. package/dist/backends/gui/select.d.ts +14 -5
  18. package/dist/backends/gui/select.d.ts.map +1 -1
  19. package/dist/backends/gui/select.js +42 -31
  20. package/dist/backends/gui/select.js.map +1 -1
  21. package/dist/backends/gui/tooltip.cjs +22 -3
  22. package/dist/backends/gui/tooltip.d.ts +12 -4
  23. package/dist/backends/gui/tooltip.d.ts.map +1 -1
  24. package/dist/backends/gui/tooltip.js +22 -3
  25. package/dist/backends/gui/tooltip.js.map +1 -1
  26. package/dist/chat/Chat.cjs +23 -1
  27. package/dist/chat/Chat.d.ts +6 -3
  28. package/dist/chat/Chat.d.ts.map +1 -1
  29. package/dist/chat/Chat.js +23 -1
  30. package/dist/chat/Chat.js.map +1 -1
  31. package/dist/chat/Inspector.cjs +51 -0
  32. package/dist/chat/Inspector.d.ts +49 -0
  33. package/dist/chat/Inspector.d.ts.map +1 -0
  34. package/dist/chat/Inspector.js +49 -0
  35. package/dist/chat/Inspector.js.map +1 -0
  36. package/dist/chat/Message.cjs +3 -1
  37. package/dist/chat/Message.d.ts +3 -1
  38. package/dist/chat/Message.d.ts.map +1 -1
  39. package/dist/chat/Message.js +3 -1
  40. package/dist/chat/Message.js.map +1 -1
  41. package/dist/chat/Parts.cjs +159 -0
  42. package/dist/chat/Parts.d.ts +186 -0
  43. package/dist/chat/Parts.d.ts.map +1 -0
  44. package/dist/chat/Parts.js +153 -0
  45. package/dist/chat/Parts.js.map +1 -0
  46. package/dist/chat/Persona.cjs +34 -0
  47. package/dist/chat/Persona.d.ts +37 -0
  48. package/dist/chat/Persona.d.ts.map +1 -0
  49. package/dist/chat/Persona.js +30 -0
  50. package/dist/chat/Persona.js.map +1 -0
  51. package/dist/chat/Preview.cjs +42 -0
  52. package/dist/chat/Preview.d.ts +36 -0
  53. package/dist/chat/Preview.d.ts.map +1 -0
  54. package/dist/chat/Preview.js +40 -0
  55. package/dist/chat/Preview.js.map +1 -0
  56. package/dist/chat/directive.cjs +272 -0
  57. package/dist/chat/directive.d.ts +167 -0
  58. package/dist/chat/directive.d.ts.map +1 -0
  59. package/dist/chat/directive.js +266 -0
  60. package/dist/chat/directive.js.map +1 -0
  61. package/dist/chat/index.cjs +59 -4
  62. package/dist/chat/index.d.ts +31 -3
  63. package/dist/chat/index.d.ts.map +1 -1
  64. package/dist/chat/index.js +31 -3
  65. package/dist/chat/index.js.map +1 -1
  66. package/dist/gallery.html +4 -4
  67. package/dist/styles.css +3 -3
  68. package/dist/theme.css +3 -3
  69. package/package.json +7 -1
@@ -1,4 +1,4 @@
1
- 'use client';
1
+ "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  /**
4
4
  * Select — the compound picker on @hanzogui/select.
@@ -9,34 +9,43 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  * `SelectGroup`. An item is written `<SelectItem value="x">Label</SelectItem>`
10
10
  * and the numbering always matches render order.
11
11
  */
12
- import { Select as GuiSelect, SelectSeparator as GuiSelectSeparator, XStack } from '@hanzo/gui';
13
- import { Check, ChevronDown, ChevronUp } from '@hanzogui/lucide-icons-2';
14
- import { Children, cloneElement, isValidElement, } from 'react';
15
- import { ink } from './ink.js';
16
- import { slot } from './slot.js';
17
- import { touch } from './gesture.js';
18
- import { CONTROL_H, FIELD } from './control.js';
12
+ import { Children, cloneElement, createContext, isValidElement, useContext, } from "react";
13
+ import { Select as GuiSelect, SelectSeparator as GuiSelectSeparator, XStack, } from "@hanzo/gui";
14
+ import { Check, ChevronDown, ChevronUp } from "@hanzogui/lucide-icons-2";
15
+ import { CONTROL_H, FIELD } from "./control.js";
16
+ import { touch } from "./gesture.js";
17
+ import { ink } from "./ink.js";
18
+ import { slot } from "./slot.js";
19
19
  const ROW_H = 32;
20
20
  const TRIGGER_H = CONTROL_H;
21
- const Select = GuiSelect;
21
+ /**
22
+ * Disabling the control is one fact with two spellings: gui puts `disabled` on
23
+ * the Trigger, the compound API puts it on the root. The root declares it and
24
+ * the trigger honours it, so a call site can say either and mean the same thing.
25
+ */
26
+ const Disabled = /* @__PURE__ */ createContext(false);
27
+ const Select = /* @__PURE__ */ Object.assign(({ disabled = false, ...props }) => (_jsx(Disabled.Provider, { value: disabled, children: _jsx(GuiSelect, { ...props }) })), GuiSelect);
22
28
  const SelectGroup = GuiSelect.Group;
23
29
  const SelectValue = GuiSelect.Value;
24
- const SelectTrigger = ({ children, ...props }) => (_jsxs(GuiSelect.Trigger, { ...slot('select-trigger'), unstyled: true, ...FIELD, items: "center", justify: "space-between", gap: "$2",
25
- // A FLOOR, not a pin. `height` alone clips a child taller than the box, and
26
- // the build stays green while it does — that is why 01ac46dce moved Button
27
- // off a pinned height. Select and Input kept theirs, so the same trap was
28
- // still armed in the two controls that sit in every form.
29
- height: "auto", minHeight: TRIGGER_H,
30
- // The trigger states its own vertical padding because otherwise something
31
- // else states it. `unstyled` does not survive gui's ListItem (it is
32
- // destructured into a local and never reaches the frame), so the frame
33
- // styles itself at `size: '$true'` and writes `paddingVertical: $3.5` — and
34
- // under `height: auto` that padding, not the floor, is what decides the box:
35
- // 14 + a 20px line + 14 + 2px of border rendered a 50px Select beside a 36px
36
- // Input. At 0 the floor decides again and `items="center"` does the
37
- // centring, which is exactly how the Input already behaves.
38
- py: 0, cursor: "pointer", ...touch(TRIGGER_H, 44, 'y'), ...props, children: [ink(children, undefined, { size: '$3' }), _jsx(GuiSelect.Icon, { children: _jsx(ChevronDown, { size: 16, opacity: 0.5 }) })] }));
39
- const SelectItem = ({ children, ...props }) => (_jsxs(GuiSelect.Item, { ...slot('select-item'), unstyled: true, index: props.index ?? 0, items: "center", gap: "$2", minH: ROW_H, pl: "$2", pr: "$7", rounded: "$2", cursor: "pointer", ...touch(ROW_H, 44, 'y'), hoverStyle: { bg: '$raised' }, focusStyle: { bg: '$raised' }, ...props, children: [_jsx(GuiSelect.ItemText, { children: children }), _jsx(XStack, { position: "absolute", r: "$2", items: "center", justify: "center", pointerEvents: "none", children: _jsx(GuiSelect.ItemIndicator, { children: _jsx(Check, { size: 16 }) }) })] }));
30
+ const SelectTrigger = ({ children, disabled, ...props }) => {
31
+ const inherited = useContext(Disabled);
32
+ return (_jsxs(GuiSelect.Trigger, { ...slot("select-trigger"), unstyled: true, disabled: disabled ?? inherited, ...FIELD, items: "center", justify: "space-between", gap: "$2",
33
+ // A FLOOR, not a pin. `height` alone clips a child taller than the box, and
34
+ // the build stays green while it does — that is why 01ac46dce moved Button
35
+ // off a pinned height. Select and Input kept theirs, so the same trap was
36
+ // still armed in the two controls that sit in every form.
37
+ height: "auto", minHeight: TRIGGER_H,
38
+ // The trigger states its own vertical padding because otherwise something
39
+ // else states it. `unstyled` does not survive gui's ListItem (it is
40
+ // destructured into a local and never reaches the frame), so the frame
41
+ // styles itself at `size: '$true'` and writes `paddingVertical: $3.5` — and
42
+ // under `height: auto` that padding, not the floor, is what decides the box:
43
+ // 14 + a 20px line + 14 + 2px of border rendered a 50px Select beside a 36px
44
+ // Input. At 0 the floor decides again and `items="center"` does the
45
+ // centring, which is exactly how the Input already behaves.
46
+ py: 0, cursor: "pointer", ...touch(TRIGGER_H, 44, "y"), ...props, children: [ink(children, undefined, { size: "$3" }), _jsx(GuiSelect.Icon, { children: _jsx(ChevronDown, { size: 16, opacity: 0.5 }) })] }));
47
+ };
48
+ const SelectItem = ({ children, ...props }) => (_jsxs(GuiSelect.Item, { ...slot("select-item"), unstyled: true, index: props.index ?? 0, items: "center", gap: "$2", minH: ROW_H, pl: "$2", pr: "$7", rounded: "$2", cursor: "pointer", ...touch(ROW_H, 44, "y"), hoverStyle: { bg: "$raised" }, focusStyle: { bg: "$raised" }, ...props, children: [_jsx(GuiSelect.ItemText, { children: children }), _jsx(XStack, { position: "absolute", r: "$2", items: "center", justify: "center", pointerEvents: "none", children: _jsx(GuiSelect.ItemIndicator, { children: _jsx(Check, { size: 16 }) }) })] }));
40
49
  /** Depth-first stamp of `index` onto every `SelectItem` in render order. */
41
50
  const stampIndices = (children, next) => Children.map(children, (child) => {
42
51
  if (!isValidElement(child))
@@ -44,15 +53,17 @@ const stampIndices = (children, next) => Children.map(children, (child) => {
44
53
  if (child.type === SelectItem)
45
54
  return cloneElement(child, { index: next() });
46
55
  const kids = child.props.children;
47
- return kids === undefined ? child : cloneElement(child, undefined, stampIndices(kids, next));
56
+ return kids === undefined
57
+ ? child
58
+ : cloneElement(child, undefined, stampIndices(kids, next));
48
59
  });
49
- const SelectScrollUpButton = (props) => (_jsx(GuiSelect.ScrollUpButton, { ...slot('select-scroll-up-button'), items: "center", justify: "center", py: "$1", ...props, children: _jsx(ChevronUp, { size: 16 }) }));
50
- const SelectScrollDownButton = (props) => (_jsx(GuiSelect.ScrollDownButton, { ...slot('select-scroll-down-button'), items: "center", justify: "center", py: "$1", ...props, children: _jsx(ChevronDown, { size: 16 }) }));
60
+ const SelectScrollUpButton = (props) => (_jsx(GuiSelect.ScrollUpButton, { ...slot("select-scroll-up-button"), items: "center", justify: "center", py: "$1", ...props, children: _jsx(ChevronUp, { size: 16 }) }));
61
+ const SelectScrollDownButton = (props) => (_jsx(GuiSelect.ScrollDownButton, { ...slot("select-scroll-down-button"), items: "center", justify: "center", py: "$1", ...props, children: _jsx(ChevronDown, { size: 16 }) }));
51
62
  const SelectContent = ({ children, ...props }) => {
52
63
  let n = 0;
53
- return (_jsxs(GuiSelect.Content, { ...slot('select-content'), ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(GuiSelect.Viewport, { minW: 128, p: "$1", bg: "$panel", borderWidth: 1, borderColor: "$borderColor", rounded: "$4", children: stampIndices(children, () => n++) }), _jsx(SelectScrollDownButton, {})] }));
64
+ return (_jsxs(GuiSelect.Content, { ...slot("select-content"), ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(GuiSelect.Viewport, { minW: 128, p: "$1", bg: "$panel", borderWidth: 1, borderColor: "$borderColor", rounded: "$4", children: stampIndices(children, () => n++) }), _jsx(SelectScrollDownButton, {})] }));
54
65
  };
55
- const SelectLabel = (props) => (_jsx(GuiSelect.Label, { ...slot('select-label'), px: "$2", py: "$1.5", fontSize: "$1", color: "$quiet", ...props }));
56
- const SelectSeparator = (props) => (_jsx(GuiSelectSeparator, { ...slot('select-separator'), my: "$1", borderColor: "$borderColor", ...props }));
66
+ const SelectLabel = (props) => (_jsx(GuiSelect.Label, { ...slot("select-label"), px: "$2", py: "$1.5", fontSize: "$1", color: "$quiet", ...props }));
67
+ const SelectSeparator = (props) => (_jsx(GuiSelectSeparator, { ...slot("select-separator"), my: "$1", borderColor: "$borderColor", ...props }));
57
68
  export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, };
58
69
  //# sourceMappingURL=select.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/backends/gui/select.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/backends/gui/select.tsx"],"names":[],"mappings":"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"}
@@ -3,20 +3,39 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.TooltipProvider = exports.TooltipContent = exports.TooltipTrigger = exports.Tooltip = void 0;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
- /** Tooltip — hover/focus hint. `TooltipProvider` is gui's `TooltipGroup`. */
6
+ /**
7
+ * Tooltip — hover/focus hint. `TooltipProvider` is gui's `TooltipGroup`.
8
+ *
9
+ * gui keeps the offset on the tooltip ROOT while the compound API spells it on
10
+ * Content, as `sideOffset`. One value, one owner: the root holds it, Content
11
+ * publishes into it — the same split `popover` resolves, for the same reason.
12
+ */
7
13
  const gui_1 = require("@hanzo/gui");
14
+ const react_1 = require("react");
8
15
  const portal_theme_1 = require("../../product/menu/portal-theme.cjs");
9
16
  const ink_1 = require("./ink.cjs");
10
17
  const slot_1 = require("./slot.cjs");
11
18
  const DEFAULT_OFFSET = 4;
12
- const Tooltip = (props) => (0, jsx_runtime_1.jsx)(gui_1.Tooltip, { offset: DEFAULT_OFFSET, ...props });
19
+ const Publish = /* @__PURE__ */ (0, react_1.createContext)(null);
20
+ const Tooltip = ({ offset = DEFAULT_OFFSET, ...props }) => {
21
+ const [placed, setPlaced] = (0, react_1.useState)({});
22
+ const publish = (0, react_1.useCallback)((p) => setPlaced((prev) => ({ ...prev, ...p })), []);
23
+ return ((0, jsx_runtime_1.jsx)(Publish.Provider, { value: publish, children: (0, jsx_runtime_1.jsx)(gui_1.Tooltip, { offset: placed.offset ?? offset, ...props }) }));
24
+ };
13
25
  exports.Tooltip = Tooltip;
14
26
  const TooltipTrigger = gui_1.Tooltip.Trigger;
15
27
  exports.TooltipTrigger = TooltipTrigger;
16
28
  const TooltipProvider = gui_1.TooltipGroup;
17
29
  exports.TooltipProvider = TooltipProvider;
18
- const TooltipContent = ({ sideOffset: _sideOffset, children, ...props }) => {
30
+ const TooltipContent = ({ sideOffset, children, ...props }) => {
19
31
  const themeName = (0, portal_theme_1.useThemeName)();
32
+ const publish = (0, react_1.useContext)(Publish);
33
+ // Only a Content that names an offset has anything to say about it; an absent
34
+ // one leaves whatever the root was given standing.
35
+ (0, react_1.useEffect)(() => {
36
+ if (sideOffset !== undefined)
37
+ publish?.({ offset: sideOffset });
38
+ }, [publish, sideOffset]);
20
39
  return ((0, jsx_runtime_1.jsx)(portal_theme_1.PortalTheme, { name: themeName, children: (0, jsx_runtime_1.jsx)(gui_1.Tooltip.Content, { ...(0, slot_1.slot)('tooltip-content'), bg: "$panel", borderWidth: 1, borderColor: "$borderColor", rounded: "$3", px: "$3", py: "$1.5", ...props, children: (0, ink_1.ink)(children, undefined, { size: '$1' }) }) }));
21
40
  };
22
41
  exports.TooltipContent = TooltipContent;
@@ -1,13 +1,21 @@
1
- /** Tooltip — hover/focus hint. `TooltipProvider` is gui's `TooltipGroup`. */
1
+ /**
2
+ * Tooltip — hover/focus hint. `TooltipProvider` is gui's `TooltipGroup`.
3
+ *
4
+ * gui keeps the offset on the tooltip ROOT while the compound API spells it on
5
+ * Content, as `sideOffset`. One value, one owner: the root holds it, Content
6
+ * publishes into it — the same split `popover` resolves, for the same reason.
7
+ */
2
8
  import { Tooltip as GuiTooltip, TooltipGroup } from '@hanzo/gui';
3
9
  import { type ComponentProps } from 'react';
4
- export type TooltipProps = ComponentProps<typeof GuiTooltip>;
10
+ export type TooltipProps = Omit<ComponentProps<typeof GuiTooltip>, 'offset'> & {
11
+ offset?: number;
12
+ };
5
13
  export type TooltipContentProps = ComponentProps<typeof GuiTooltip.Content> & {
6
14
  sideOffset?: number;
7
15
  };
8
- declare const Tooltip: (props: TooltipProps) => import("react").JSX.Element;
16
+ declare const Tooltip: ({ offset, ...props }: TooltipProps) => import("react").JSX.Element;
9
17
  declare const TooltipTrigger: typeof GuiTooltip.Trigger;
10
18
  declare const TooltipProvider: typeof TooltipGroup;
11
- declare const TooltipContent: ({ sideOffset: _sideOffset, children, ...props }: TooltipContentProps) => import("react").JSX.Element;
19
+ declare const TooltipContent: ({ sideOffset, children, ...props }: TooltipContentProps) => import("react").JSX.Element;
12
20
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
13
21
  //# sourceMappingURL=tooltip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/tooltip.tsx"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,OAAO,CAAA;AAOtD,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,CAAA;AAC5D,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAErG,QAAA,MAAM,OAAO,UAAW,YAAY,gCAAsD,CAAA;AAC1F,QAAA,MAAM,cAAc,EAAE,OAAO,UAAU,CAAC,OAA4B,CAAA;AACpE,QAAA,MAAM,eAAe,EAAE,OAAO,YAA2B,CAAA;AAEzD,QAAA,MAAM,cAAc,oDAAqD,mBAAmB,gCAkB3F,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
1
+ {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/tooltip.tsx"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,OAAO,CAAA;AAYd,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,UAAU,CAAC,EAAE,QAAQ,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAClG,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAErG,QAAA,MAAM,OAAO,yBAA2C,YAAY,gCAQnE,CAAA;AACD,QAAA,MAAM,cAAc,EAAE,OAAO,UAAU,CAAC,OAA4B,CAAA;AACpE,QAAA,MAAM,eAAe,EAAE,OAAO,YAA2B,CAAA;AAEzD,QAAA,MAAM,cAAc,uCAAwC,mBAAmB,gCAwB9E,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
@@ -1,16 +1,35 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- /** Tooltip — hover/focus hint. `TooltipProvider` is gui's `TooltipGroup`. */
3
+ /**
4
+ * Tooltip — hover/focus hint. `TooltipProvider` is gui's `TooltipGroup`.
5
+ *
6
+ * gui keeps the offset on the tooltip ROOT while the compound API spells it on
7
+ * Content, as `sideOffset`. One value, one owner: the root holds it, Content
8
+ * publishes into it — the same split `popover` resolves, for the same reason.
9
+ */
4
10
  import { Tooltip as GuiTooltip, TooltipGroup } from '@hanzo/gui';
11
+ import { createContext, useCallback, useContext, useEffect, useState, } from 'react';
5
12
  import { PortalTheme, useThemeName } from '../../product/menu/portal-theme.js';
6
13
  import { ink } from './ink.js';
7
14
  import { slot } from './slot.js';
8
15
  const DEFAULT_OFFSET = 4;
9
- const Tooltip = (props) => _jsx(GuiTooltip, { offset: DEFAULT_OFFSET, ...props });
16
+ const Publish = /* @__PURE__ */ createContext(null);
17
+ const Tooltip = ({ offset = DEFAULT_OFFSET, ...props }) => {
18
+ const [placed, setPlaced] = useState({});
19
+ const publish = useCallback((p) => setPlaced((prev) => ({ ...prev, ...p })), []);
20
+ return (_jsx(Publish.Provider, { value: publish, children: _jsx(GuiTooltip, { offset: placed.offset ?? offset, ...props }) }));
21
+ };
10
22
  const TooltipTrigger = GuiTooltip.Trigger;
11
23
  const TooltipProvider = TooltipGroup;
12
- const TooltipContent = ({ sideOffset: _sideOffset, children, ...props }) => {
24
+ const TooltipContent = ({ sideOffset, children, ...props }) => {
13
25
  const themeName = useThemeName();
26
+ const publish = useContext(Publish);
27
+ // Only a Content that names an offset has anything to say about it; an absent
28
+ // one leaves whatever the root was given standing.
29
+ useEffect(() => {
30
+ if (sideOffset !== undefined)
31
+ publish?.({ offset: sideOffset });
32
+ }, [publish, sideOffset]);
14
33
  return (_jsx(PortalTheme, { name: themeName, children: _jsx(GuiTooltip.Content, { ...slot('tooltip-content'), bg: "$panel", borderWidth: 1, borderColor: "$borderColor", rounded: "$3", px: "$3", py: "$1.5", ...props, children: ink(children, undefined, { size: '$1' }) }) }));
15
34
  };
16
35
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../../../src/backends/gui/tooltip.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,6EAA6E;AAC7E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEhE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,MAAM,cAAc,GAAG,CAAC,CAAA;AAKxB,MAAM,OAAO,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,KAAC,UAAU,IAAC,MAAM,EAAE,cAAc,KAAM,KAAK,GAAI,CAAA;AAC1F,MAAM,cAAc,GAA8B,UAAU,CAAC,OAAO,CAAA;AACpE,MAAM,eAAe,GAAwB,YAAY,CAAA;AAEzD,MAAM,cAAc,GAAG,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAuB,EAAE,EAAE;IAC9F,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,OAAO,CACL,KAAC,WAAW,IAAC,IAAI,EAAE,SAAS,YAC1B,KAAC,UAAU,CAAC,OAAO,OACb,IAAI,CAAC,iBAAiB,CAAC,EAC3B,EAAE,EAAC,QAAQ,EACX,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,OAAO,EAAC,IAAI,EACZ,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,MAAM,KACL,KAAK,YAER,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GACtB,GACT,CACf,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
1
+ {"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../../../src/backends/gui/tooltip.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAChE,OAAO,EACL,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,GAET,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,MAAM,cAAc,GAAG,CAAC,CAAA;AAKxB,MAAM,OAAO,GAAG,eAAe,CAAC,aAAa,CAA+B,IAAI,CAAC,CAAA;AAKjF,MAAM,OAAO,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,KAAK,EAAgB,EAAE,EAAE;IACtE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACxF,OAAO,CACL,KAAC,OAAO,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YAC9B,KAAC,UAAU,IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,KAAM,KAAK,GAAI,GACzC,CACpB,CAAA;AACH,CAAC,CAAA;AACD,MAAM,cAAc,GAA8B,UAAU,CAAC,OAAO,CAAA;AACpE,MAAM,eAAe,GAAwB,YAAY,CAAA;AAEzD,MAAM,cAAc,GAAG,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAuB,EAAE,EAAE;IACjF,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;IACnC,8EAA8E;IAC9E,mDAAmD;IACnD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAA;IACjE,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAA;IACzB,OAAO,CACL,KAAC,WAAW,IAAC,IAAI,EAAE,SAAS,YAC1B,KAAC,UAAU,CAAC,OAAO,OACb,IAAI,CAAC,iBAAiB,CAAC,EAC3B,EAAE,EAAC,QAAQ,EACX,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,OAAO,EAAC,IAAI,EACZ,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,MAAM,KACL,KAAK,YAER,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GACtB,GACT,CACf,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
@@ -28,6 +28,10 @@ const jsx_runtime_1 = require("react/jsx-runtime");
28
28
  * component reads it, and lifting it would put a keystroke through the surface's
29
29
  * state on every letter.
30
30
  *
31
+ * That same call now draws a turn whose content is a LIST, through `Parts` — so
32
+ * an image, a tool call, a citation and an artifact reach the screen with
33
+ * nothing added at the call site. They used to be dropped there.
34
+ *
31
35
  * No transport, no store, no routing — `@hanzo/ui` stays fetch-free, so nothing
32
36
  * here imports `@hanzo/ai`. `messages` is read structurally, which is what lets
33
37
  * that hold while the two packages still compose exactly.
@@ -38,8 +42,26 @@ const ink_1 = require("../backends/gui/ink.cjs");
38
42
  const slot_1 = require("../backends/gui/slot.cjs");
39
43
  const Composer_1 = require("./Composer.cjs");
40
44
  const Message_1 = require("./Message.cjs");
45
+ const Parts_1 = require("./Parts.cjs");
41
46
  const Thread_1 = require("./Thread.cjs");
42
47
  const words_1 = require("./words.cjs");
48
+ /**
49
+ * A turn's content, drawn by what it is.
50
+ *
51
+ * A string is prose and always was. A LIST goes to `Parts`, which is the change:
52
+ * it used to go to `words`, which keeps the text and drops the image, the tool
53
+ * call and the citation — so a surface passing the wire's own turns saw only the
54
+ * prose in them, and had to write its own switch to see the rest.
55
+ *
56
+ * Nothing regresses on the way through. `Parts` joins adjacent prose before it
57
+ * draws (the wire splits a sentence mid-word), and a part whose type it does not
58
+ * know contributes its text, so an all-text turn renders the identical string
59
+ * `words` produced.
60
+ *
61
+ * The cast is the one place the open wire meets the closed union, and it is safe
62
+ * in exactly that direction: `Parts` reads `type` before it reads anything else.
63
+ */
64
+ const draw = (said) => typeof said === 'string' || said == null ? ((0, ink_1.ink)((0, words_1.words)(said))) : ((0, jsx_runtime_1.jsx)(Parts_1.Parts, { parts: said }));
43
65
  function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, composer, ...thread }) {
44
66
  const [draft, setDraft] = (0, react_1.useState)('');
45
67
  // Clearing here rather than in an effect on `messages` is what keeps a send
@@ -63,5 +85,5 @@ function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, e
63
85
  // from the composer lands on a `display: contents` wrapper or on the page,
64
86
  // and then reports a component that is fine as broken, or one that is broken
65
87
  // as fine.
66
- return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, width: "100%", ...(0, slot_1.slot)('chat'), children: [messages.length === 0 && empty ? (empty) : ((0, jsx_runtime_1.jsx)(Thread_1.Thread, { flex: 1, ...thread, children: messages.map((turn, i) => ((0, jsx_runtime_1.jsx)(Message_1.Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : (0, ink_1.ink)((0, words_1.words)(turn.content)) }, turn.id))) })), (0, jsx_runtime_1.jsx)(Composer_1.Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer })] }));
88
+ return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, width: "100%", ...(0, slot_1.slot)('chat'), children: [messages.length === 0 && empty ? (empty) : ((0, jsx_runtime_1.jsx)(Thread_1.Thread, { flex: 1, ...thread, children: messages.map((turn, i) => ((0, jsx_runtime_1.jsx)(Message_1.Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : draw(turn.content) }, turn.id))) })), (0, jsx_runtime_1.jsx)(Composer_1.Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer })] }));
67
89
  }
@@ -21,7 +21,7 @@ export interface Turn {
21
21
  * over: a completion's content is `string | ContentPart[]` (text beside an
22
22
  * image), so a turn holding an attachment could not be handed to this at all.
23
23
  * Narrowing the wire in a component fed BY the wire just relocates the
24
- * mismatch to every caller. `words` is the flattener.
24
+ * mismatch to every caller. `words` flattens it to prose; `Parts` draws it.
25
25
  */
26
26
  content?: Said;
27
27
  }
@@ -45,12 +45,15 @@ export interface ChatProps extends Omit<ThreadProps, 'children' | 'ref'> {
45
45
  /** End the turn in flight. Absent, the composer offers no stop. */
46
46
  stop?: () => void;
47
47
  /**
48
- * Render a turn's body. Defaults to its text.
48
+ * Render a turn's body. Defaults to `Parts` for a list and the words for a
49
+ * string.
49
50
  *
50
51
  * A surface with a markdown pipeline passes it here — the plugin set is
51
52
  * per-surface (nine plugins, one plugin, or a regex under a bundle ceiling
52
53
  * that cannot afford a parser), so this package ships none and renders the
53
- * words plainly until someone says otherwise.
54
+ * words plainly until someone says otherwise. The usual form hands the
55
+ * pipeline to `Parts` rather than replacing it:
56
+ * `body={(t) => <Parts parts={t.content as MessagePart[]} prose={md} />}`.
54
57
  */
55
58
  body?: (turn: Turn) => ReactNode;
56
59
  /** Shown instead of the thread while nothing has been said. */
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"AAgCA,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAI7D,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAW,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAS,KAAK,IAAI,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;;;GAOG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,IAAI,CAAA;CACf;AAED,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,KAAK,CAAC;IACtE,sCAAsC;IACtC,QAAQ,EAAE,IAAI,EAAE,CAAA;IAChB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;;;OAUG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAA;IACjB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAA;IAChC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;CAClC;AAED,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAiB,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,GAAG,MAAM,EACV,EAAE,SAAS,+BAoDX"}
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"AAoCA,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAI7D,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAW,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAE9C,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAS,KAAK,IAAI,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;;;GAOG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,IAAI,CAAA;CACf;AAED,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,KAAK,CAAC;IACtE,sCAAsC;IACtC,QAAQ,EAAE,IAAI,EAAE,CAAA;IAChB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;;;OAUG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAA;IACjB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAA;IAChC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;CAClC;AAyBD,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAiB,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,GAAG,MAAM,EACV,EAAE,SAAS,+BAoDX"}
package/dist/chat/Chat.js CHANGED
@@ -25,6 +25,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
25
25
  * component reads it, and lifting it would put a keystroke through the surface's
26
26
  * state on every letter.
27
27
  *
28
+ * That same call now draws a turn whose content is a LIST, through `Parts` — so
29
+ * an image, a tool call, a citation and an artifact reach the screen with
30
+ * nothing added at the call site. They used to be dropped there.
31
+ *
28
32
  * No transport, no store, no routing — `@hanzo/ui` stays fetch-free, so nothing
29
33
  * here imports `@hanzo/ai`. `messages` is read structurally, which is what lets
30
34
  * that hold while the two packages still compose exactly.
@@ -35,8 +39,26 @@ import { ink } from '../backends/gui/ink.js';
35
39
  import { slot } from '../backends/gui/slot.js';
36
40
  import { Composer } from './Composer.js';
37
41
  import { Message } from './Message.js';
42
+ import { Parts } from './Parts.js';
38
43
  import { Thread } from './Thread.js';
39
44
  import { words } from './words.js';
45
+ /**
46
+ * A turn's content, drawn by what it is.
47
+ *
48
+ * A string is prose and always was. A LIST goes to `Parts`, which is the change:
49
+ * it used to go to `words`, which keeps the text and drops the image, the tool
50
+ * call and the citation — so a surface passing the wire's own turns saw only the
51
+ * prose in them, and had to write its own switch to see the rest.
52
+ *
53
+ * Nothing regresses on the way through. `Parts` joins adjacent prose before it
54
+ * draws (the wire splits a sentence mid-word), and a part whose type it does not
55
+ * know contributes its text, so an all-text turn renders the identical string
56
+ * `words` produced.
57
+ *
58
+ * The cast is the one place the open wire meets the closed union, and it is safe
59
+ * in exactly that direction: `Parts` reads `type` before it reads anything else.
60
+ */
61
+ const draw = (said) => typeof said === 'string' || said == null ? (ink(words(said))) : (_jsx(Parts, { parts: said }));
40
62
  export function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, composer, ...thread }) {
41
63
  const [draft, setDraft] = useState('');
42
64
  // Clearing here rather than in an effect on `messages` is what keeps a send
@@ -60,6 +82,6 @@ export function Chat({ messages, streaming = false, send: onSend, stop: onStop,
60
82
  // from the composer lands on a `display: contents` wrapper or on the page,
61
83
  // and then reports a component that is fine as broken, or one that is broken
62
84
  // as fine.
63
- return (_jsxs(YStack, { flex: 1, width: "100%", ...slot('chat'), children: [messages.length === 0 && empty ? (empty) : (_jsx(Thread, { flex: 1, ...thread, children: messages.map((turn, i) => (_jsx(Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : ink(words(turn.content)) }, turn.id))) })), _jsx(Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer })] }));
85
+ return (_jsxs(YStack, { flex: 1, width: "100%", ...slot('chat'), children: [messages.length === 0 && empty ? (empty) : (_jsx(Thread, { flex: 1, ...thread, children: messages.map((turn, i) => (_jsx(Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : draw(turn.content) }, turn.id))) })), _jsx(Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer })] }));
64
86
  }
65
87
  //# sourceMappingURL=Chat.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAE7D,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAsB,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,OAAO,EAAa,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAa,MAAM,SAAS,CAAA;AA2D1C,MAAM,UAAU,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,GAAG,KAAK,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,GAAG,MAAM,EACC;IACV,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAEtC,4EAA4E;IAC5E,yEAAyE;IACzE,iEAAiE;IACjE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,QAAQ,CAAC,EAAE,CAAC,CAAA;QACZ,MAAM,CAAC,IAAI,CAAC,CAAA;IACd,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IAEnB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IAEhC,4EAA4E;IAC5E,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,8EAA8E;IAC9E,gFAAgF;IAChF,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,WAAW;IACX,OAAO,CACL,MAAC,MAAM,IAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,aAC3C,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAChC,KAAK,CACN,CAAC,CAAC,CAAC,CACF,KAAC,MAAM,IAAC,IAAI,EAAE,CAAC,KAAM,MAAM,YACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACzB,KAAC,OAAO,IAEN,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,IAAI,EAAE,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,YAEzD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAJxC,IAAI,CAAC,EAAE,CAKJ,CACX,CAAC,GACK,CACV,EACD,KAAC,QAAQ,IACP,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,IAAI,EACZ,IAAI,EAAE,SAAS,KACX,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC1B,QAAQ,GACZ,IACK,CACV,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAE7D,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAsB,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,OAAO,EAAa,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,KAAK,EAAoB,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAa,MAAM,SAAS,CAAA;AA8D1C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,GAAG,CAAC,IAAU,EAAE,EAAE,CAC1B,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CACzC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CACjB,CAAC,CAAC,CAAC,CACF,KAAC,KAAK,IAAC,KAAK,EAAE,IAAqB,GAAI,CACxC,CAAA;AAEH,MAAM,UAAU,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,GAAG,KAAK,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,GAAG,MAAM,EACC;IACV,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAEtC,4EAA4E;IAC5E,yEAAyE;IACzE,iEAAiE;IACjE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,QAAQ,CAAC,EAAE,CAAC,CAAA;QACZ,MAAM,CAAC,IAAI,CAAC,CAAA;IACd,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IAEnB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IAEhC,4EAA4E;IAC5E,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,8EAA8E;IAC9E,gFAAgF;IAChF,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,WAAW;IACX,OAAO,CACL,MAAC,MAAM,IAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,aAC3C,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAChC,KAAK,CACN,CAAC,CAAC,CAAC,CACF,KAAC,MAAM,IAAC,IAAI,EAAE,CAAC,KAAM,MAAM,YACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACzB,KAAC,OAAO,IAEN,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,IAAI,EAAE,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,YAEzD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAJlC,IAAI,CAAC,EAAE,CAKJ,CACX,CAAC,GACK,CACV,EACD,KAAC,QAAQ,IACP,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,IAAI,EACZ,IAAI,EAAE,SAAS,KACX,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC1B,QAAQ,GACZ,IACK,CACV,CAAA;AACH,CAAC"}
@@ -0,0 +1,51 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Inspector = Inspector;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * Inspector — what the agent did, beside what it said.
8
+ *
9
+ * The thread carries the answer. This carries the evidence: a summary at the
10
+ * top, then the run's own regions underneath — what it was given, what it
11
+ * produced, what ran on the way. It is the pane a person reads to decide
12
+ * whether to believe the answer, which is why the summary is first and the
13
+ * detail is under it rather than the other way round.
14
+ *
15
+ * It is the CONTENTS of the right rail, not the rail. `Aside` is the column —
16
+ * the border, the width, the fact that it is a column at all — and this goes
17
+ * inside it. Two components because a surface hides the rail at narrow widths
18
+ * by not rendering it, and that decision has nothing to do with what is in it.
19
+ *
20
+ * ONE inspector, whatever the run was. A section carries `facts` (name to
21
+ * value) or `parts` (drawn by `Parts`), and `MessagePart` already covers every
22
+ * shape a run produces: tool calls and their results for a chat turn, files and
23
+ * console output for a coding run, `citation` for a research run's sources, an
24
+ * `artifact` for anything it made. A second panel per kind of run would be four
25
+ * copies of this file disagreeing about spacing.
26
+ *
27
+ * A section with nothing in it does not render, so a caller passes the same
28
+ * list every time and does not write the emptiness checks.
29
+ */
30
+ const gui_1 = require("@hanzo/gui");
31
+ const slot_1 = require("../backends/gui/slot.cjs");
32
+ const Code_1 = require("./Code.cjs");
33
+ const Parts_1 = require("./Parts.cjs");
34
+ const filled = (section) => (section.facts != null && Object.keys(section.facts).length > 0) ||
35
+ (section.parts != null && section.parts.length > 0);
36
+ function Inspector({ title = 'Run', summary, sections = [], placeholder, prose, onRetry, onOpen, onSource, ...props }) {
37
+ const shown = sections.filter(filled);
38
+ const bare = summary == null && shown.length === 0;
39
+ return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('inspector'), flex: 1, minH: 0, width: "100%", ...props, children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { items: "center", px: "$1", pb: "$2", shrink: 0, children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$soft", fontWeight: "600", children: title }) }), (0, jsx_runtime_1.jsx)(gui_1.ScrollView, { flex: 1, showsVerticalScrollIndicator: false, children: (0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$4", pb: "$4", children: [summary ? ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('inspector-summary'), p: "$3", gap: "$2", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$panel", children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$ink", children: summary }) })) : null, shown.map((section) => ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('inspector-section'), gap: "$2", children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$quiet", fontWeight: "600", children: section.name }), section.facts ? (0, jsx_runtime_1.jsx)(Table, { facts: section.facts }) : null, section.parts?.length ? ((0, jsx_runtime_1.jsx)(Parts_1.Parts, { parts: section.parts, prose: prose, onRetry: onRetry, onOpen: onOpen, onSource: onSource })) : null] }, section.name))), bare && placeholder != null ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$soft", children: placeholder })) : null] }) })] }));
40
+ }
41
+ /**
42
+ * A record, as rows.
43
+ *
44
+ * A string is its own presentation; anything else goes through `Code`, because
45
+ * a nested object flattened into a line is unreadable and `show` already
46
+ * serialises one safely. That is the only rule here, and it is why this is a
47
+ * dozen lines rather than a formatting library.
48
+ */
49
+ function Table({ facts }) {
50
+ return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('inspector-facts'), rounded: "$4", borderWidth: 1, borderColor: "$borderColor", overflow: "hidden", children: Object.entries(facts).map(([name, value], i) => ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$1.5", px: "$3", py: "$2", borderTopWidth: i === 0 ? 0 : 1, borderColor: "$borderColor", children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$quiet", children: name }), typeof value === 'string' ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$ink", children: value })) : ((0, jsx_runtime_1.jsx)(Code_1.Code, { language: "json", children: (0, Parts_1.show)(value) }))] }, name))) }));
51
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Inspector — what the agent did, beside what it said.
3
+ *
4
+ * The thread carries the answer. This carries the evidence: a summary at the
5
+ * top, then the run's own regions underneath — what it was given, what it
6
+ * produced, what ran on the way. It is the pane a person reads to decide
7
+ * whether to believe the answer, which is why the summary is first and the
8
+ * detail is under it rather than the other way round.
9
+ *
10
+ * It is the CONTENTS of the right rail, not the rail. `Aside` is the column —
11
+ * the border, the width, the fact that it is a column at all — and this goes
12
+ * inside it. Two components because a surface hides the rail at narrow widths
13
+ * by not rendering it, and that decision has nothing to do with what is in it.
14
+ *
15
+ * ONE inspector, whatever the run was. A section carries `facts` (name to
16
+ * value) or `parts` (drawn by `Parts`), and `MessagePart` already covers every
17
+ * shape a run produces: tool calls and their results for a chat turn, files and
18
+ * console output for a coding run, `citation` for a research run's sources, an
19
+ * `artifact` for anything it made. A second panel per kind of run would be four
20
+ * copies of this file disagreeing about spacing.
21
+ *
22
+ * A section with nothing in it does not render, so a caller passes the same
23
+ * list every time and does not write the emptiness checks.
24
+ */
25
+ import { YStack } from '@hanzo/gui';
26
+ import type { ComponentProps, ReactNode } from 'react';
27
+ import type { Facts } from './directive.js';
28
+ import { type MessagePart, type PartActions } from './Parts.js';
29
+ /** One region of a run. Either half may be present; both is fine. */
30
+ export interface Section {
31
+ /** The heading. */
32
+ name: string;
33
+ /** Drawn as a table of name and value. */
34
+ facts?: Facts;
35
+ /** Drawn by `Parts` — steps, artifacts, sources, files. */
36
+ parts?: readonly MessagePart[];
37
+ }
38
+ export interface InspectorProps extends PartActions, Omit<ComponentProps<typeof YStack>, 'children'> {
39
+ /** The pane's own heading. */
40
+ title?: string;
41
+ /** One paragraph: what the run did. Absent, no summary block draws. */
42
+ summary?: string;
43
+ /** The regions, in order. Empty ones are skipped. */
44
+ sections?: readonly Section[];
45
+ /** Shown when there is no summary and every section is empty. */
46
+ placeholder?: ReactNode;
47
+ }
48
+ export declare function Inspector({ title, summary, sections, placeholder, prose, onRetry, onOpen, onSource, ...props }: InspectorProps): import("react").JSX.Element;
49
+ //# sourceMappingURL=Inspector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Inspector.d.ts","sourceRoot":"","sources":["../../src/chat/Inspector.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAmC,MAAM,EAAE,MAAM,YAAY,CAAA;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAA;AAEzE,qEAAqE;AACrE,MAAM,WAAW,OAAO;IACtB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,0CAA0C;IAC1C,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;CAC/B;AAMD,MAAM,WAAW,cACf,SAAQ,WAAW,EACjB,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC;IACjD,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;IAC7B,iEAAiE;IACjE,WAAW,CAAC,EAAE,SAAS,CAAA;CACxB;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAa,EACb,OAAO,EACP,QAAa,EACb,WAAW,EACX,KAAK,EACL,OAAO,EACP,MAAM,EACN,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,+BAyDhB"}
@@ -0,0 +1,49 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Inspector — what the agent did, beside what it said.
5
+ *
6
+ * The thread carries the answer. This carries the evidence: a summary at the
7
+ * top, then the run's own regions underneath — what it was given, what it
8
+ * produced, what ran on the way. It is the pane a person reads to decide
9
+ * whether to believe the answer, which is why the summary is first and the
10
+ * detail is under it rather than the other way round.
11
+ *
12
+ * It is the CONTENTS of the right rail, not the rail. `Aside` is the column —
13
+ * the border, the width, the fact that it is a column at all — and this goes
14
+ * inside it. Two components because a surface hides the rail at narrow widths
15
+ * by not rendering it, and that decision has nothing to do with what is in it.
16
+ *
17
+ * ONE inspector, whatever the run was. A section carries `facts` (name to
18
+ * value) or `parts` (drawn by `Parts`), and `MessagePart` already covers every
19
+ * shape a run produces: tool calls and their results for a chat turn, files and
20
+ * console output for a coding run, `citation` for a research run's sources, an
21
+ * `artifact` for anything it made. A second panel per kind of run would be four
22
+ * copies of this file disagreeing about spacing.
23
+ *
24
+ * A section with nothing in it does not render, so a caller passes the same
25
+ * list every time and does not write the emptiness checks.
26
+ */
27
+ import { ScrollView, SizableText, XStack, YStack } from '@hanzo/gui';
28
+ import { slot } from '../backends/gui/slot.js';
29
+ import { Code } from './Code.js';
30
+ import { Parts, show } from './Parts.js';
31
+ const filled = (section) => (section.facts != null && Object.keys(section.facts).length > 0) ||
32
+ (section.parts != null && section.parts.length > 0);
33
+ export function Inspector({ title = 'Run', summary, sections = [], placeholder, prose, onRetry, onOpen, onSource, ...props }) {
34
+ const shown = sections.filter(filled);
35
+ const bare = summary == null && shown.length === 0;
36
+ return (_jsxs(YStack, { ...slot('inspector'), flex: 1, minH: 0, width: "100%", ...props, children: [_jsx(XStack, { items: "center", px: "$1", pb: "$2", shrink: 0, children: _jsx(SizableText, { size: "$1", color: "$soft", fontWeight: "600", children: title }) }), _jsx(ScrollView, { flex: 1, showsVerticalScrollIndicator: false, children: _jsxs(YStack, { gap: "$4", pb: "$4", children: [summary ? (_jsx(YStack, { ...slot('inspector-summary'), p: "$3", gap: "$2", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$panel", children: _jsx(SizableText, { size: "$2", color: "$ink", children: summary }) })) : null, shown.map((section) => (_jsxs(YStack, { ...slot('inspector-section'), gap: "$2", children: [_jsx(SizableText, { size: "$1", color: "$quiet", fontWeight: "600", children: section.name }), section.facts ? _jsx(Table, { facts: section.facts }) : null, section.parts?.length ? (_jsx(Parts, { parts: section.parts, prose: prose, onRetry: onRetry, onOpen: onOpen, onSource: onSource })) : null] }, section.name))), bare && placeholder != null ? (_jsx(SizableText, { size: "$2", color: "$soft", children: placeholder })) : null] }) })] }));
37
+ }
38
+ /**
39
+ * A record, as rows.
40
+ *
41
+ * A string is its own presentation; anything else goes through `Code`, because
42
+ * a nested object flattened into a line is unreadable and `show` already
43
+ * serialises one safely. That is the only rule here, and it is why this is a
44
+ * dozen lines rather than a formatting library.
45
+ */
46
+ function Table({ facts }) {
47
+ return (_jsx(YStack, { ...slot('inspector-facts'), rounded: "$4", borderWidth: 1, borderColor: "$borderColor", overflow: "hidden", children: Object.entries(facts).map(([name, value], i) => (_jsxs(YStack, { gap: "$1.5", px: "$3", py: "$2", borderTopWidth: i === 0 ? 0 : 1, borderColor: "$borderColor", children: [_jsx(SizableText, { size: "$1", color: "$quiet", children: name }), typeof value === 'string' ? (_jsx(SizableText, { size: "$2", color: "$ink", children: value })) : (_jsx(Code, { language: "json", children: show(value) }))] }, name))) }));
48
+ }
49
+ //# sourceMappingURL=Inspector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Inspector.js","sourceRoot":"","sources":["../../src/chat/Inspector.tsx"],"names":[],"mappings":"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"}
@@ -12,7 +12,9 @@ const jsx_runtime_1 = require("react/jsx-runtime");
12
12
  * turn is a muted aside. The contrast is what says who is speaking, so there is
13
13
  * no name and no timestamp, and `icon` is opt-in.
14
14
  *
15
- * Content is `children`: the markdown pipeline stays with the surface.
15
+ * Content is `children`: the markdown pipeline stays with the surface. A turn
16
+ * that arrived as a list of parts puts `<Parts>` there — `Chat` does exactly
17
+ * that — so this component keeps knowing nothing about the wire.
16
18
  */
17
19
  const gui_1 = require("@hanzo/gui");
18
20
  const ink_1 = require("../backends/gui/ink.cjs");
@@ -6,7 +6,9 @@
6
6
  * turn is a muted aside. The contrast is what says who is speaking, so there is
7
7
  * no name and no timestamp, and `icon` is opt-in.
8
8
  *
9
- * Content is `children`: the markdown pipeline stays with the surface.
9
+ * Content is `children`: the markdown pipeline stays with the surface. A turn
10
+ * that arrived as a list of parts puts `<Parts>` there — `Chat` does exactly
11
+ * that — so this component keeps knowing nothing about the wire.
10
12
  */
11
13
  import { XStack } from '@hanzo/gui';
12
14
  import type { ComponentProps, ReactNode } from 'react';