@hanzo/ui 8.1.3 → 8.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/backends/gui/textarea.cjs +35 -3
  2. package/dist/backends/gui/textarea.d.ts +34 -5
  3. package/dist/backends/gui/textarea.d.ts.map +1 -1
  4. package/dist/backends/gui/textarea.js +35 -3
  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 +16 -10
  12. package/dist/chat/Composer.d.ts +59 -3
  13. package/dist/chat/Composer.d.ts.map +1 -1
  14. package/dist/chat/Composer.js +16 -10
  15. package/dist/chat/Composer.js.map +1 -1
  16. package/dist/chat/Failure.cjs +2 -2
  17. package/dist/chat/Failure.d.ts +29 -3
  18. package/dist/chat/Failure.d.ts.map +1 -1
  19. package/dist/chat/Failure.js +2 -2
  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 +10 -4
  27. package/dist/chat/Message.d.ts +42 -3
  28. package/dist/chat/Message.d.ts.map +1 -1
  29. package/dist/chat/Message.js +10 -4
  30. package/dist/chat/Message.js.map +1 -1
  31. package/dist/chat/Sources.cjs +33 -10
  32. package/dist/chat/Sources.d.ts +46 -6
  33. package/dist/chat/Sources.d.ts.map +1 -1
  34. package/dist/chat/Sources.js +32 -9
  35. package/dist/chat/Sources.js.map +1 -1
  36. package/dist/chat/Step.cjs +2 -2
  37. package/dist/chat/Step.d.ts +4 -3
  38. package/dist/chat/Step.d.ts.map +1 -1
  39. package/dist/chat/Step.js +2 -2
  40. package/dist/chat/Step.js.map +1 -1
  41. package/dist/chat/Thread.cjs +38 -13
  42. package/dist/chat/Thread.d.ts +55 -3
  43. package/dist/chat/Thread.d.ts.map +1 -1
  44. package/dist/chat/Thread.js +38 -13
  45. package/dist/chat/Thread.js.map +1 -1
  46. package/dist/chat/index.cjs +19 -2
  47. package/dist/chat/index.d.ts +18 -1
  48. package/dist/chat/index.d.ts.map +1 -1
  49. package/dist/chat/index.js +18 -1
  50. package/dist/chat/index.js.map +1 -1
  51. package/dist/chat/pure.cjs +41 -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 +35 -0
  55. package/dist/chat/pure.js.map +1 -0
  56. package/dist/chat/send.cjs +10 -1
  57. package/dist/chat/send.d.ts +9 -0
  58. package/dist/chat/send.d.ts.map +1 -1
  59. package/dist/chat/send.js +10 -1
  60. package/dist/chat/send.js.map +1 -1
  61. package/dist/chat/stick.cjs +1 -1
  62. package/dist/chat/stick.js +1 -1
  63. package/dist/gallery.cjs +5 -4
  64. package/dist/gallery.d.ts.map +1 -1
  65. package/dist/gallery.js +5 -4
  66. package/dist/gallery.js.map +1 -1
  67. package/dist/product/CopyButton.cjs +2 -2
  68. package/dist/product/CopyButton.d.ts +12 -2
  69. package/dist/product/CopyButton.d.ts.map +1 -1
  70. package/dist/product/CopyButton.js +2 -2
  71. package/dist/product/CopyButton.js.map +1 -1
  72. package/dist/product/pure.cjs +12 -1
  73. package/dist/product/pure.d.ts +2 -0
  74. package/dist/product/pure.d.ts.map +1 -1
  75. package/dist/product/pure.js +7 -0
  76. package/dist/product/pure.js.map +1 -1
  77. package/dist/styles.css +14 -2
  78. package/package.json +7 -1
@@ -1,11 +1,63 @@
1
- import { type ReactNode } from 'react';
2
- export interface ThreadProps {
1
+ /**
2
+ * Thread — the scrolling column of turns.
3
+ *
4
+ * It does the one thing every surface had re-solved: follow a streaming answer
5
+ * to the bottom, and stop following the instant the reader scrolls up. The
6
+ * decision is `pinned()`, asserted without a DOM; this component only wires it
7
+ * to the platform's scroll view, so momentum and keyboard stay the host's.
8
+ *
9
+ * That decision is now the fleet's only answer to "am I at the bottom", which
10
+ * had five: 50px in two places, 97%-of-height in a third, an
11
+ * `IntersectionObserver` at a 0.85 ratio in a fourth, and on the thread itself
12
+ * nothing at all — hanzo.app `/chat` ran `scrollIntoView({behavior:'smooth'})`
13
+ * on every `messages` change, and since a streaming turn rewrites `messages`
14
+ * per SSE delta, scrolling up to re-read was undone several times a second.
15
+ *
16
+ * Measured in Chromium against the packed tarball, 2500 tokens at 4ms:
17
+ * following holds a 0px gap through 2501 commits; parked at offset 0 the reader
18
+ * STAYS at 0 while content grows 1015 → 1375; returning to the end resumes
19
+ * following at 0px.
20
+ *
21
+ * There is no `onLayout` here any more, and nothing is lost with it. It was
22
+ * passed to keep a `track` ref current, gui does not implement it on this
23
+ * component so React forwarded it to the DOM as an unknown handler — the noise
24
+ * hanzo.app reported — and the ref it fed was WRITE-ONLY: `track` was read in
25
+ * exactly one place, `onScroll`, which rebuilds all three numbers from the
26
+ * event before reading them. So the handler was dead, the state it kept was
27
+ * dead, and the measurement the two together looked like they were doing was
28
+ * being done properly a few lines below the whole time. The scroll event
29
+ * carries `layoutMeasurement`; nothing else needs to ask.
30
+ */
31
+ import { ScrollView, YStack, type GetRef } from '@hanzo/gui';
32
+ import { type ComponentProps, type ReactNode } from 'react';
33
+ import { type Track } from './stick.js';
34
+ type Scroller = GetRef<typeof ScrollView> & {
35
+ scrollToEnd(o: {
36
+ animated: boolean;
37
+ }): void;
38
+ };
39
+ export interface ThreadProps extends Omit<ComponentProps<typeof ScrollView>, 'children' | 'onScroll'> {
3
40
  children?: ReactNode;
4
41
  /** Reading-measure cap. Pass `0` to fill the container. */
5
42
  maxWidth?: number;
6
43
  /** How near the end still counts as "at the bottom", in px. */
7
44
  slack?: number;
8
45
  gap?: number;
46
+ /**
47
+ * The scroll, after the follow decision is made — with `at`, the answer.
48
+ *
49
+ * Three separate consumers need this element and this fact: the follow
50
+ * decision, a scroll-to-bottom button, and a surface's own turn-offset
51
+ * bookkeeping. Deciding privately and publishing nothing is what left each of
52
+ * them measuring the scroller again, differently.
53
+ */
54
+ onScroll?: (event: unknown, at: {
55
+ pinned: boolean;
56
+ track: Track;
57
+ }) => void;
58
+ /** The column that holds the turns, for a surface that needs to reach it. */
59
+ column?: Omit<ComponentProps<typeof YStack>, 'children'>;
9
60
  }
10
- export declare function Thread({ children, maxWidth, slack, gap }: ThreadProps): import("react/jsx-runtime").JSX.Element;
61
+ export declare const Thread: import("react").ForwardRefExoticComponent<Omit<ThreadProps, "ref"> & import("react").RefAttributes<Scroller>>;
62
+ export {};
11
63
  //# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;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;;;;;;;OAOG;IACH,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"}
@@ -7,34 +7,59 @@ import { jsx as _jsx } from "react/jsx-runtime";
7
7
  * to the bottom, and stop following the instant the reader scrolls up. The
8
8
  * decision is `pinned()`, asserted without a DOM; this component only wires it
9
9
  * to the platform's scroll view, so momentum and keyboard stay the host's.
10
+ *
11
+ * That decision is now the fleet's only answer to "am I at the bottom", which
12
+ * had five: 50px in two places, 97%-of-height in a third, an
13
+ * `IntersectionObserver` at a 0.85 ratio in a fourth, and on the thread itself
14
+ * nothing at all — hanzo.app `/chat` ran `scrollIntoView({behavior:'smooth'})`
15
+ * on every `messages` change, and since a streaming turn rewrites `messages`
16
+ * per SSE delta, scrolling up to re-read was undone several times a second.
17
+ *
18
+ * Measured in Chromium against the packed tarball, 2500 tokens at 4ms:
19
+ * following holds a 0px gap through 2501 commits; parked at offset 0 the reader
20
+ * STAYS at 0 while content grows 1015 → 1375; returning to the end resumes
21
+ * following at 0px.
22
+ *
23
+ * There is no `onLayout` here any more, and nothing is lost with it. It was
24
+ * passed to keep a `track` ref current, gui does not implement it on this
25
+ * component so React forwarded it to the DOM as an unknown handler — the noise
26
+ * hanzo.app reported — and the ref it fed was WRITE-ONLY: `track` was read in
27
+ * exactly one place, `onScroll`, which rebuilds all three numbers from the
28
+ * event before reading them. So the handler was dead, the state it kept was
29
+ * dead, and the measurement the two together looked like they were doing was
30
+ * being done properly a few lines below the whole time. The scroll event
31
+ * carries `layoutMeasurement`; nothing else needs to ask.
10
32
  */
11
33
  import { ScrollView, YStack } from '@hanzo/gui';
12
- import { useCallback, useRef } from 'react';
34
+ import { forwardRef, useCallback, useRef } from 'react';
13
35
  import { slot } from '../backends/gui/slot.js';
14
36
  import { pinned, SLACK } from './stick.js';
15
37
  /** Reading-measure cap for prose, in px. */
16
38
  const MEASURE = 768;
17
- export function Thread({ children, maxWidth = MEASURE, slack = SLACK, gap = 24 }) {
39
+ export const Thread = /* @__PURE__ */ forwardRef(function Thread({ children, maxWidth = MEASURE, slack = SLACK, gap = 24, onScroll, column, ...props }, ref) {
18
40
  const view = useRef(null);
19
- const track = useRef({ offset: 0, viewport: 0, content: 0 });
20
41
  const follow = useRef(true);
42
+ // Ours to scroll with, the caller's because three consumers need this node.
43
+ const hold = useCallback((el) => {
44
+ view.current = el;
45
+ if (typeof ref === 'function')
46
+ ref(el);
47
+ else if (ref)
48
+ ref.current = el;
49
+ }, [ref]);
21
50
  const grew = useCallback(() => {
22
51
  if (follow.current)
23
52
  view.current?.scrollToEnd({ animated: false });
24
53
  }, []);
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) => {
54
+ return (_jsx(ScrollView, { ref: hold, ...slot('thread'), flex: 1, width: "100%", scrollEventThrottle: 16, onContentSizeChange: grew, onScroll: (e) => {
31
55
  const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent;
32
- track.current = {
56
+ const track = {
33
57
  offset: contentOffset.y,
34
58
  viewport: layoutMeasurement.height,
35
59
  content: contentSize.height,
36
60
  };
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
- }
61
+ follow.current = pinned(track, slack);
62
+ onScroll?.(e, { pinned: follow.current, track });
63
+ }, ...props, children: _jsx(YStack, { ...slot('thread-column'), width: "100%", gap: gap, py: gap, ...(maxWidth ? { maxW: maxWidth, self: 'center', px: '$3' } : null), ...column, children: children }) }));
64
+ });
40
65
  //# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;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;AAyBnB,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,4EAA4E;IAC5E,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,6 +1,6 @@
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
  *
@@ -42,6 +42,23 @@ exports.SourceChip = exports.Sources = exports.Failure = exports.Step = exports.
42
42
  * active-id resolution. The same components serve a live conversation, a shared
43
43
  * read-only transcript and a test fixture.
44
44
  *
45
+ * Every component here spreads its residual props onto its own element, and
46
+ * `Message`, `Thread` and `Composer` publish a way through to the part they own
47
+ * (`body`, `column`, `field`). They did not, and that closed list was the ONE
48
+ * thing keeping hanzo/chat from adopting `Message`: its scroll machinery
49
+ * addresses turns by `id`, `SelectionAsk` finds one with
50
+ * `closest('.message-render')`, and its turn wears a fleet-wide `glass`
51
+ * material against a `bg` welded to `$color3`. None of it exotic, all of it
52
+ * free with a spread — gui forwards what it does not recognise, which is the
53
+ * mechanism `slot()` is already built on.
54
+ *
55
+ * `@hanzo/ui/chat/pure` is the same module's decisions with nothing attached:
56
+ * `sends`, `ready`, `pinned`, `SLACK`. It exists because `import('@hanzo/ui/chat')`
57
+ * cannot load in Node, so no script and no spec could reach them. They are also
58
+ * re-exported from `@hanzo/ui/product/pure`, because they are not chat rules —
59
+ * ten of the fifteen files importing `sends` in hanzo.app are a SQL editor, a
60
+ * file explorer, a command palette, a rename field.
61
+ *
45
62
  * Styling is `$` tokens throughout, never literal colours, so each brand retunes
46
63
  * through its own theme and nothing here carries a Hanzo mark — which is what
47
64
  * lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
@@ -93,4 +110,4 @@ var Failure_1 = require("./Failure.cjs");
93
110
  Object.defineProperty(exports, "Failure", { enumerable: true, get: function () { return Failure_1.Failure; } });
94
111
  var Sources_1 = require("./Sources.cjs");
95
112
  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; } });
113
+ Object.defineProperty(exports, "SourceCard", { enumerable: true, get: function () { return Sources_1.SourceCard; } });
@@ -39,6 +39,23 @@
39
39
  * active-id resolution. The same components serve a live conversation, a shared
40
40
  * read-only transcript and a test fixture.
41
41
  *
42
+ * Every component here spreads its residual props onto its own element, and
43
+ * `Message`, `Thread` and `Composer` publish a way through to the part they own
44
+ * (`body`, `column`, `field`). They did not, and that closed list was the ONE
45
+ * thing keeping hanzo/chat from adopting `Message`: its scroll machinery
46
+ * addresses turns by `id`, `SelectionAsk` finds one with
47
+ * `closest('.message-render')`, and its turn wears a fleet-wide `glass`
48
+ * material against a `bg` welded to `$color3`. None of it exotic, all of it
49
+ * free with a spread — gui forwards what it does not recognise, which is the
50
+ * mechanism `slot()` is already built on.
51
+ *
52
+ * `@hanzo/ui/chat/pure` is the same module's decisions with nothing attached:
53
+ * `sends`, `ready`, `pinned`, `SLACK`. It exists because `import('@hanzo/ui/chat')`
54
+ * cannot load in Node, so no script and no spec could reach them. They are also
55
+ * re-exported from `@hanzo/ui/product/pure`, because they are not chat rules —
56
+ * ten of the fifteen files importing `sends` in hanzo.app are a SQL editor, a
57
+ * file explorer, a command palette, a rename field.
58
+ *
42
59
  * Styling is `$` tokens throughout, never literal colours, so each brand retunes
43
60
  * through its own theme and nothing here carries a Hanzo mark — which is what
44
61
  * lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
@@ -62,5 +79,5 @@ export { Header, HeaderButton, ShareButton, AsideToggle, Aside, type HeaderProps
62
79
  export { Code, type CodeProps } from './Code.js';
63
80
  export { Step, type StepProps, type Ran } from './Step.js';
64
81
  export { Failure, type FailureProps } from './Failure.js';
65
- export { Sources, SourceChip, type Source, type SourcesProps, type SourceChipProps, } from './Sources.js';
82
+ export { Sources, SourceCard, type Source, type SourcesProps, type SourceCardProps, } from './Sources.js';
66
83
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,QAAQ,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAA;AAEtD,OAAO,EACL,OAAO,EACP,UAAU,EACV,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,QAAQ,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAA;AAEtD,OAAO,EACL,OAAO,EACP,UAAU,EACV,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAA"}
@@ -39,6 +39,23 @@
39
39
  * active-id resolution. The same components serve a live conversation, a shared
40
40
  * read-only transcript and a test fixture.
41
41
  *
42
+ * Every component here spreads its residual props onto its own element, and
43
+ * `Message`, `Thread` and `Composer` publish a way through to the part they own
44
+ * (`body`, `column`, `field`). They did not, and that closed list was the ONE
45
+ * thing keeping hanzo/chat from adopting `Message`: its scroll machinery
46
+ * addresses turns by `id`, `SelectionAsk` finds one with
47
+ * `closest('.message-render')`, and its turn wears a fleet-wide `glass`
48
+ * material against a `bg` welded to `$color3`. None of it exotic, all of it
49
+ * free with a spread — gui forwards what it does not recognise, which is the
50
+ * mechanism `slot()` is already built on.
51
+ *
52
+ * `@hanzo/ui/chat/pure` is the same module's decisions with nothing attached:
53
+ * `sends`, `ready`, `pinned`, `SLACK`. It exists because `import('@hanzo/ui/chat')`
54
+ * cannot load in Node, so no script and no spec could reach them. They are also
55
+ * re-exported from `@hanzo/ui/product/pure`, because they are not chat rules —
56
+ * ten of the fifteen files importing `sends` in hanzo.app are a SQL editor, a
57
+ * file explorer, a command palette, a rename field.
58
+ *
42
59
  * Styling is `$` tokens throughout, never literal colours, so each brand retunes
43
60
  * through its own theme and nothing here carries a Hanzo mark — which is what
44
61
  * lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
@@ -62,5 +79,5 @@ export { Header, HeaderButton, ShareButton, AsideToggle, Aside, } from './Header
62
79
  export { Code } from './Code.js';
63
80
  export { Step } from './Step.js';
64
81
  export { Failure } from './Failure.js';
65
- export { Sources, SourceChip, } from './Sources.js';
82
+ export { Sources, SourceCard, } from './Sources.js';
66
83
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAsB,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAa,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,GASZ,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,GAMN,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAkB,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,IAAI,EAA4B,MAAM,QAAQ,CAAA;AACvD,OAAO,EAAE,OAAO,EAAqB,MAAM,WAAW,CAAA;AAEtD,OAAO,EACL,OAAO,EACP,UAAU,GAIX,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAsB,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,KAAK,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AACxE,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAa,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,GASZ,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,GAMN,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAkB,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,IAAI,EAA4B,MAAM,QAAQ,CAAA;AACvD,OAAO,EAAE,OAAO,EAAqB,MAAM,WAAW,CAAA;AAEtD,OAAO,EACL,OAAO,EACP,UAAU,GAIX,MAAM,WAAW,CAAA"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ // @hanzo/ui/chat/pure — the conversation's decisions, without the conversation.
3
+ //
4
+ // Every module here is a function over values: no @hanzo/gui, no React, no DOM,
5
+ // no side effects. Same shape and same reason as `@hanzo/ui/product/pure`, and
6
+ // the reason is measured — `import('@hanzo/ui/chat')` in Node dies on
7
+ // `SyntaxError: Unexpected token 'typeof'`, so a script, a Playwright spec or a
8
+ // server-side caller could not reach these at all. They had to stand up a
9
+ // browser to ask whether Enter sends.
10
+ //
11
+ // import { sends, ready, pinned, SLACK } from '@hanzo/ui/chat/pure'
12
+ //
13
+ // These are not chat rules and the chat-shaped import was hiding that. Of the
14
+ // fifteen files in hanzo.app that import `sends`, TEN are not chat: a repo-URL
15
+ // field, two project renames, the SQL editor, the file explorer, the SEO tab,
16
+ // the workspace menu, the console prompt, an uploader and the command palette.
17
+ // "Does this keystroke commit this field" is the same question wherever a field
18
+ // takes Enter. `@hanzo/ui/product/pure` re-exports all four for exactly that
19
+ // reader — the one who is not writing chat and would never look here.
20
+ //
21
+ // It is the same mistake `CopyButton` made, recorded in this module's own
22
+ // barrel: a general thing reachable only through a chat-shaped door gets
23
+ // rewritten by everyone who does not think to open that door. hanzo/chat had
24
+ // THREE Enter rules, and two of them (`AnswerComposer`, `SelectionAsk`) tested
25
+ // `Enter && !shiftKey` straight off the event — so Enter-to-accept an IME
26
+ // candidate submitted a half-typed word for Japanese, Chinese and Korean
27
+ // writers. `sends` had the fix from the day it was written and nobody could
28
+ // reach it.
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.SLACK = exports.pinned = exports.sends = exports.ready = void 0;
31
+ // Enter, and whether a draft may go. The IME guard is the whole point; read
32
+ // `sends` before writing another one.
33
+ var send_1 = require("./send.cjs");
34
+ Object.defineProperty(exports, "ready", { enumerable: true, get: function () { return send_1.ready; } });
35
+ Object.defineProperty(exports, "sends", { enumerable: true, get: function () { return send_1.sends; } });
36
+ // Stay-at-the-bottom, as a distance test. The fleet's one answer to "am I at
37
+ // the bottom", which had five: 50px twice, 97%-of-height, an
38
+ // IntersectionObserver at a 0.85 ratio, and on one thread nothing at all.
39
+ var stick_1 = require("./stick.cjs");
40
+ Object.defineProperty(exports, "pinned", { enumerable: true, get: function () { return stick_1.pinned; } });
41
+ Object.defineProperty(exports, "SLACK", { enumerable: true, get: function () { return stick_1.SLACK; } });
@@ -0,0 +1,3 @@
1
+ export { ready, sends, type Mods } from './send.js';
2
+ export { pinned, SLACK, type Track } from './stick.js';
3
+ //# sourceMappingURL=pure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pure.d.ts","sourceRoot":"","sources":["../../src/chat/pure.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAKhD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,35 @@
1
+ // @hanzo/ui/chat/pure — the conversation's decisions, without the conversation.
2
+ //
3
+ // Every module here is a function over values: no @hanzo/gui, no React, no DOM,
4
+ // no side effects. Same shape and same reason as `@hanzo/ui/product/pure`, and
5
+ // the reason is measured — `import('@hanzo/ui/chat')` in Node dies on
6
+ // `SyntaxError: Unexpected token 'typeof'`, so a script, a Playwright spec or a
7
+ // server-side caller could not reach these at all. They had to stand up a
8
+ // browser to ask whether Enter sends.
9
+ //
10
+ // import { sends, ready, pinned, SLACK } from '@hanzo/ui/chat/pure'
11
+ //
12
+ // These are not chat rules and the chat-shaped import was hiding that. Of the
13
+ // fifteen files in hanzo.app that import `sends`, TEN are not chat: a repo-URL
14
+ // field, two project renames, the SQL editor, the file explorer, the SEO tab,
15
+ // the workspace menu, the console prompt, an uploader and the command palette.
16
+ // "Does this keystroke commit this field" is the same question wherever a field
17
+ // takes Enter. `@hanzo/ui/product/pure` re-exports all four for exactly that
18
+ // reader — the one who is not writing chat and would never look here.
19
+ //
20
+ // It is the same mistake `CopyButton` made, recorded in this module's own
21
+ // barrel: a general thing reachable only through a chat-shaped door gets
22
+ // rewritten by everyone who does not think to open that door. hanzo/chat had
23
+ // THREE Enter rules, and two of them (`AnswerComposer`, `SelectionAsk`) tested
24
+ // `Enter && !shiftKey` straight off the event — so Enter-to-accept an IME
25
+ // candidate submitted a half-typed word for Japanese, Chinese and Korean
26
+ // writers. `sends` had the fix from the day it was written and nobody could
27
+ // reach it.
28
+ // Enter, and whether a draft may go. The IME guard is the whole point; read
29
+ // `sends` before writing another one.
30
+ export { ready, sends } from './send.js';
31
+ // Stay-at-the-bottom, as a distance test. The fleet's one answer to "am I at
32
+ // the bottom", which had five: 50px twice, 97%-of-height, an
33
+ // IntersectionObserver at a 0.85 ratio, and on one thread nothing at all.
34
+ export { pinned, SLACK } from './stick.js';
35
+ //# sourceMappingURL=pure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pure.js","sourceRoot":"","sources":["../../src/chat/pure.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,sEAAsE;AACtE,gFAAgF;AAChF,0EAA0E;AAC1E,sCAAsC;AACtC,EAAE;AACF,sEAAsE;AACtE,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,sEAAsE;AACtE,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,6EAA6E;AAC7E,+EAA+E;AAC/E,0EAA0E;AAC1E,yEAAyE;AACzE,4EAA4E;AAC5E,YAAY;AAEZ,4EAA4E;AAC5E,sCAAsC;AACtC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAa,MAAM,QAAQ,CAAA;AAEhD,6EAA6E;AAC7E,6DAA6D;AAC7D,0EAA0E;AAC1E,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA"}
@@ -1,4 +1,4 @@
1
- 'use client';"use strict";
1
+ "use strict";
2
2
  /**
3
3
  * The two decisions a composer makes, as pure functions.
4
4
  *
@@ -27,6 +27,15 @@ const claimed = (key, mods) => mods.isComposing === true || key === 'Process' ||
27
27
  * reachable from the keyboard. Cmd/Ctrl+Enter always sends — it is the force-send
28
28
  * every surface already taught its users, and it holds even with Shift down.
29
29
  * A keystroke the IME has claimed belongs to the IME, never to the composer.
30
+ *
31
+ * HAND IT `e.nativeEvent`, NEVER `e`. React's synthetic KeyboardEvent does not
32
+ * carry `isComposing` or `keyCode`, so passing the synthetic event gets one of
33
+ * the three IME signals instead of three, type-checks cleanly, reads correctly
34
+ * at the call site, and puts the mid-candidate submit straight back for every
35
+ * Japanese, Chinese and Korean writer. That is the entire bug this function
36
+ * exists to end, and it is re-introducible in one character.
37
+ *
38
+ * onKeyDown={(e) => { if (sends(e.key, e.nativeEvent)) { … } }}
30
39
  */
31
40
  const sends = (key, mods = {}) => {
32
41
  if (key !== 'Enter' || claimed(key, mods))
@@ -22,6 +22,15 @@ export interface Mods {
22
22
  * reachable from the keyboard. Cmd/Ctrl+Enter always sends — it is the force-send
23
23
  * every surface already taught its users, and it holds even with Shift down.
24
24
  * A keystroke the IME has claimed belongs to the IME, never to the composer.
25
+ *
26
+ * HAND IT `e.nativeEvent`, NEVER `e`. React's synthetic KeyboardEvent does not
27
+ * carry `isComposing` or `keyCode`, so passing the synthetic event gets one of
28
+ * the three IME signals instead of three, type-checks cleanly, reads correctly
29
+ * at the call site, and puts the mid-candidate submit straight back for every
30
+ * Japanese, Chinese and Korean writer. That is the entire bug this function
31
+ * exists to end, and it is re-introducible in one character.
32
+ *
33
+ * onKeyDown={(e) => { if (sends(e.key, e.nativeEvent)) { … } }}
25
34
  */
26
35
  export declare const sends: (key: string, mods?: Mods) => boolean;
27
36
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/chat/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,mEAAmE;AACnE,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAkBD;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,EAAE,OAAM,IAAS,KAAG,OAIpD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,cAAY,EAAE,kBAAgB,KAAG,OACvB,CAAA"}
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/chat/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,mEAAmE;AACnE,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAkBD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,EAAE,OAAM,IAAS,KAAG,OAIpD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,cAAY,EAAE,kBAAgB,KAAG,OACvB,CAAA"}
package/dist/chat/send.js CHANGED
@@ -1,4 +1,4 @@
1
- 'use client';/**
1
+ /**
2
2
  * The two decisions a composer makes, as pure functions.
3
3
  *
4
4
  * Every Hanzo chat surface had re-implemented both inline, and they had drifted:
@@ -24,6 +24,15 @@ const claimed = (key, mods) => mods.isComposing === true || key === 'Process' ||
24
24
  * reachable from the keyboard. Cmd/Ctrl+Enter always sends — it is the force-send
25
25
  * every surface already taught its users, and it holds even with Shift down.
26
26
  * A keystroke the IME has claimed belongs to the IME, never to the composer.
27
+ *
28
+ * HAND IT `e.nativeEvent`, NEVER `e`. React's synthetic KeyboardEvent does not
29
+ * carry `isComposing` or `keyCode`, so passing the synthetic event gets one of
30
+ * the three IME signals instead of three, type-checks cleanly, reads correctly
31
+ * at the call site, and puts the mid-candidate submit straight back for every
32
+ * Japanese, Chinese and Korean writer. That is the entire bug this function
33
+ * exists to end, and it is re-introducible in one character.
34
+ *
35
+ * onKeyDown={(e) => { if (sends(e.key, e.nativeEvent)) { … } }}
27
36
  */
28
37
  export const sends = (key, mods = {}) => {
29
38
  if (key !== 'Enter' || claimed(key, mods))
@@ -1 +1 @@
1
- {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/chat/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH,4EAA4E;AAC5E,MAAM,GAAG,GAAG,GAAG,CAAA;AAEf;;;;;;;;;GASG;AACH,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,IAAU,EAAW,EAAE,CACnD,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,GAAG,CAAA;AAExE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,OAAa,EAAE,EAAW,EAAE;IAC7D,IAAI,GAAG,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IACvD,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC/D,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAA;AACvD,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,IAAI,GAAG,KAAK,EAAE,QAAQ,GAAG,KAAK,EAAW,EAAE,CAC9E,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA"}
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/chat/send.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH,4EAA4E;AAC5E,MAAM,GAAG,GAAG,GAAG,CAAA;AAEf;;;;;;;;;GASG;AACH,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,IAAU,EAAW,EAAE,CACnD,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,GAAG,CAAA;AAExE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,OAAa,EAAE,EAAW,EAAE;IAC7D,IAAI,GAAG,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IACvD,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAC/D,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAA;AACvD,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,IAAI,GAAG,KAAK,EAAE,QAAQ,GAAG,KAAK,EAAW,EAAE,CAC9E,CAAC,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA"}
@@ -1,4 +1,4 @@
1
- 'use client';"use strict";
1
+ "use strict";
2
2
  /**
3
3
  * Stay-at-the-bottom, as a pure decision.
4
4
  *
@@ -1,4 +1,4 @@
1
- 'use client';/**
1
+ /**
2
2
  * Stay-at-the-bottom, as a pure decision.
3
3
  *
4
4
  * A thread should follow a streaming answer, but it must stop following the
package/dist/gallery.cjs CHANGED
@@ -26,10 +26,11 @@ const BUTTON_SIZES = ['default', 'sm', 'lg', 'icon', 'icon-sm', 'icon-lg'];
26
26
  const BADGE_VARIANTS = ['default', 'secondary', 'destructive', 'outline'];
27
27
  /** The chat shell is callbacks-out, and this list only needs them to exist. */
28
28
  const NOOP = () => { };
29
- /** Two, so the grid's wrap rule and the letter fallback both render. */
29
+ /** Two: one with a host and one without, so the card's second line and its
30
+ * letter fallback are both rendered rules. */
30
31
  const SOURCES = [
31
- { id: 'a', title: 'hanzo.ai', href: 'https://hanzo.ai' },
32
- { id: 'b', title: 'Reference' },
32
+ { id: 'a', title: 'The one chat surface', href: 'https://hanzo.ai', host: 'hanzo.ai' },
33
+ { id: 'b', title: 'A reference with a title long enough to reach the three-line clamp' },
33
34
  ];
34
35
  /** One section. Plain CSS on a plain div — the gallery is a harness, and laying
35
36
  * it out with the components under test would make a layout bug read as a
@@ -53,6 +54,6 @@ const Gallery = () => ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex'
53
54
  tabs: [
54
55
  { id: 'console', title: 'Console', closable: false, content: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "console" }) },
55
56
  ],
56
- }, children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "center" }) }) }) }), (0, jsx_runtime_1.jsxs)(Section, { name: "product-arrangements", children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 320 }, children: [(0, jsx_runtime_1.jsx)(Skeleton_1.Skeleton, { width: 120 }), (0, jsx_runtime_1.jsx)(Skeleton_1.Skeleton, { width: "100%", height: 72, rounded: "$4" }), (0, jsx_runtime_1.jsx)(Skeleton_1.Skeleton.Text, { lines: 3 })] }), (0, jsx_runtime_1.jsx)(TooltipAnchor_1.TooltipAnchor, { description: "Delete this agent", children: (0, jsx_runtime_1.jsx)(gui_1.Button, { children: "hinted" }) }), (0, jsx_runtime_1.jsx)(gui_1.Dialog, { open: true, children: (0, jsx_runtime_1.jsx)(DialogTemplate_1.DialogTemplate, { title: "Delete agent", description: "This removes every run recorded against it.", confirm: { label: 'Delete', tone: 'danger' }, children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "body" }) }) })] }), (0, jsx_runtime_1.jsxs)(Section, { name: "chat", children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 520, height: 320 }, children: [(0, jsx_runtime_1.jsxs)(chat_1.Header, { title: "A conversation with a long enough name to clamp", children: [(0, jsx_runtime_1.jsx)(chat_1.ShareButton, {}), (0, jsx_runtime_1.jsx)(chat_1.AsideToggle, {})] }), (0, jsx_runtime_1.jsxs)(chat_1.Thread, { children: [(0, jsx_runtime_1.jsx)(chat_1.Message, { role: "user", children: "ask" }), (0, jsx_runtime_1.jsxs)(chat_1.Message, { role: "assistant", icon: (0, jsx_runtime_1.jsx)(gui_1.Spinner, {}), actions: (0, jsx_runtime_1.jsx)(gui_1.Badge, { children: "copy" }), children: [(0, jsx_runtime_1.jsx)(chat_1.Step, { name: "shell", status: "running", detail: "git status --porcelain" }), (0, jsx_runtime_1.jsx)(chat_1.Step, { name: "write", status: "done", detail: "src/index.ts", defaultOpen: true, children: (0, jsx_runtime_1.jsx)(chat_1.Code, { language: "json", value: "{}", children: '{}' }) }), (0, jsx_runtime_1.jsx)(chat_1.Step, { name: "fetch", status: "error", detail: "timed out", children: "plain body" }), (0, jsx_runtime_1.jsx)(chat_1.Step, { name: "plan", status: "cancelled" }), (0, jsx_runtime_1.jsx)(chat_1.Code, { language: "typescript", value: "const x = 1", children: "const x = 1" }), (0, jsx_runtime_1.jsx)(chat_1.Sources, { sources: SOURCES })] }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "assistant", busy: true, children: "answering" }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "assistant", children: (0, jsx_runtime_1.jsx)(chat_1.Failure, { onRetry: NOOP, children: "The model stopped before finishing." }) }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "assistant", children: (0, jsx_runtime_1.jsx)(chat_1.Failure, { children: "Rate limited." }) }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "system", children: "note" })] }), (0, jsx_runtime_1.jsx)(chat_1.Composer, { value: "a draft", onChange: NOOP, onSend: NOOP, hint: "Enter to send", children: (0, jsx_runtime_1.jsx)(gui_1.Badge, { children: "tool" }) }), (0, jsx_runtime_1.jsx)(chat_1.Composer, { value: "", onChange: NOOP, onSend: NOOP, onStop: NOOP, busy: true })] }), (0, jsx_runtime_1.jsx)(chat_1.Aside, { children: (0, jsx_runtime_1.jsx)(chat_1.Sources, { sources: SOURCES }) }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', width: 260, height: 320 }, children: (0, jsx_runtime_1.jsxs)(chat_1.Sidebar, { children: [(0, jsx_runtime_1.jsx)(chat_1.SidebarHeader, { title: "Hanzo", onOpenSwitcher: NOOP, onSearch: NOOP, onCollapse: NOOP }), (0, jsx_runtime_1.jsx)(chat_1.SidebarNewChat, { onPress: NOOP }), (0, jsx_runtime_1.jsxs)(chat_1.SidebarScroll, { children: [(0, jsx_runtime_1.jsxs)(chat_1.SidebarSection, { label: "Today", children: [(0, jsx_runtime_1.jsx)(chat_1.SidebarItem, { active: true, onPress: NOOP, children: "Selected thread" }), (0, jsx_runtime_1.jsx)(chat_1.SidebarItem, { onPress: NOOP, children: "Another thread" })] }), (0, jsx_runtime_1.jsx)(chat_1.SidebarFolder, { name: "Archive", defaultOpen: true, children: (0, jsx_runtime_1.jsx)(chat_1.SidebarItem, { onPress: NOOP, children: "Nested thread" }) })] }), (0, jsx_runtime_1.jsx)(chat_1.SidebarUser, { name: "z", secondary: "z@hanzo.ai", onPress: NOOP, onHelp: NOOP })] }) })] }), (0, jsx_runtime_1.jsxs)(Section, { name: "box", children: [(0, jsx_runtime_1.jsx)(box_1.Box, { className: "flex items-center gap-4 px-6 py-3 rounded-lg border", children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "utility classes" }) }), (0, jsx_runtime_1.jsx)(box_1.Box, { className: "flex-col gap-2 max-w-3xl mx-auto overflow-hidden", children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "column" }) })] })] }));
57
+ }, children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "center" }) }) }) }), (0, jsx_runtime_1.jsxs)(Section, { name: "product-arrangements", children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 320 }, children: [(0, jsx_runtime_1.jsx)(Skeleton_1.Skeleton, { width: 120 }), (0, jsx_runtime_1.jsx)(Skeleton_1.Skeleton, { width: "100%", height: 72, rounded: "$4" }), (0, jsx_runtime_1.jsx)(Skeleton_1.Skeleton.Text, { lines: 3 })] }), (0, jsx_runtime_1.jsx)(TooltipAnchor_1.TooltipAnchor, { description: "Delete this agent", children: (0, jsx_runtime_1.jsx)(gui_1.Button, { children: "hinted" }) }), (0, jsx_runtime_1.jsx)(gui_1.Dialog, { open: true, children: (0, jsx_runtime_1.jsx)(DialogTemplate_1.DialogTemplate, { title: "Delete agent", description: "This removes every run recorded against it.", confirm: { label: 'Delete', tone: 'danger' }, children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "body" }) }) })] }), (0, jsx_runtime_1.jsxs)(Section, { name: "chat", children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 520, height: 320 }, children: [(0, jsx_runtime_1.jsxs)(chat_1.Header, { title: "A conversation with a long enough name to clamp", leading: (0, jsx_runtime_1.jsx)(chat_1.AsideToggle, {}), onOpenMenu: NOOP, children: [(0, jsx_runtime_1.jsx)(chat_1.ShareButton, {}), (0, jsx_runtime_1.jsx)(chat_1.AsideToggle, {})] }), (0, jsx_runtime_1.jsxs)(chat_1.Thread, { children: [(0, jsx_runtime_1.jsx)(chat_1.Message, { role: "user", children: "ask" }), (0, jsx_runtime_1.jsxs)(chat_1.Message, { role: "assistant", icon: (0, jsx_runtime_1.jsx)(gui_1.Spinner, {}), actions: (0, jsx_runtime_1.jsx)(gui_1.Badge, { children: "copy" }), children: [(0, jsx_runtime_1.jsx)(chat_1.Step, { name: "shell", status: "running", detail: "git status --porcelain" }), (0, jsx_runtime_1.jsx)(chat_1.Step, { name: "write", status: "done", detail: "src/index.ts", defaultOpen: true, children: (0, jsx_runtime_1.jsx)(chat_1.Code, { language: "json", value: "{}", children: '{}' }) }), (0, jsx_runtime_1.jsx)(chat_1.Step, { name: "fetch", status: "error", detail: "timed out", children: "plain body" }), (0, jsx_runtime_1.jsx)(chat_1.Step, { name: "plan", status: "cancelled" }), (0, jsx_runtime_1.jsx)(chat_1.Code, { language: "typescript", value: "const x = 1", children: "const x = 1" }), (0, jsx_runtime_1.jsx)(chat_1.Sources, { sources: SOURCES })] }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "assistant", busy: true, children: "answering" }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "assistant", children: (0, jsx_runtime_1.jsx)(chat_1.Failure, { onRetry: NOOP, children: "The model stopped before finishing." }) }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "assistant", children: (0, jsx_runtime_1.jsx)(chat_1.Failure, { children: "Rate limited." }) }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "user", body: { bg: '$color5', rounded: '$3' }, children: "restyled bubble" }), (0, jsx_runtime_1.jsx)(chat_1.Message, { role: "system", children: "note" })] }), (0, jsx_runtime_1.jsx)(chat_1.Composer, { value: "a draft", onChange: NOOP, onSend: NOOP, hint: "Enter to send", children: (0, jsx_runtime_1.jsx)(gui_1.Badge, { children: "tool" }) }), (0, jsx_runtime_1.jsx)(chat_1.Composer, { value: "", onChange: NOOP, onSend: NOOP, onStop: NOOP, busy: true })] }), (0, jsx_runtime_1.jsx)(chat_1.Aside, { children: (0, jsx_runtime_1.jsx)(chat_1.Sources, { sources: SOURCES }) }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', width: 260, height: 320 }, children: (0, jsx_runtime_1.jsxs)(chat_1.Sidebar, { children: [(0, jsx_runtime_1.jsx)(chat_1.SidebarHeader, { title: "Hanzo", onOpenSwitcher: NOOP, onSearch: NOOP, onCollapse: NOOP }), (0, jsx_runtime_1.jsx)(chat_1.SidebarNewChat, { onPress: NOOP }), (0, jsx_runtime_1.jsxs)(chat_1.SidebarScroll, { children: [(0, jsx_runtime_1.jsxs)(chat_1.SidebarSection, { label: "Today", children: [(0, jsx_runtime_1.jsx)(chat_1.SidebarItem, { active: true, onPress: NOOP, children: "Selected thread" }), (0, jsx_runtime_1.jsx)(chat_1.SidebarItem, { onPress: NOOP, children: "Another thread" })] }), (0, jsx_runtime_1.jsx)(chat_1.SidebarFolder, { name: "Archive", defaultOpen: true, children: (0, jsx_runtime_1.jsx)(chat_1.SidebarItem, { onPress: NOOP, children: "Nested thread" }) })] }), (0, jsx_runtime_1.jsx)(chat_1.SidebarUser, { name: "z", secondary: "z@hanzo.ai", onPress: NOOP, onHelp: NOOP })] }) })] }), (0, jsx_runtime_1.jsxs)(Section, { name: "box", children: [(0, jsx_runtime_1.jsx)(box_1.Box, { className: "flex items-center gap-4 px-6 py-3 rounded-lg border", children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "utility classes" }) }), (0, jsx_runtime_1.jsx)(box_1.Box, { className: "flex-col gap-2 max-w-3xl mx-auto overflow-hidden", children: (0, jsx_runtime_1.jsx)(gui_1.CardTitle, { children: "column" }) })] })] }));
57
58
  exports.Gallery = Gallery;
58
59
  exports.default = exports.Gallery;
@@ -1 +1 @@
1
- {"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../src/gallery.tsx"],"names":[],"mappings":"AAgHA;;;GAGG;AACH,eAAO,MAAM,OAAO,+CAkgBnB,CAAA;AAED,eAAe,OAAO,CAAA"}
1
+ {"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../src/gallery.tsx"],"names":[],"mappings":"AAiHA;;;GAGG;AACH,eAAO,MAAM,OAAO,+CA2gBnB,CAAA;AAED,eAAe,OAAO,CAAA"}
package/dist/gallery.js CHANGED
@@ -23,10 +23,11 @@ const BUTTON_SIZES = ['default', 'sm', 'lg', 'icon', 'icon-sm', 'icon-lg'];
23
23
  const BADGE_VARIANTS = ['default', 'secondary', 'destructive', 'outline'];
24
24
  /** The chat shell is callbacks-out, and this list only needs them to exist. */
25
25
  const NOOP = () => { };
26
- /** Two, so the grid's wrap rule and the letter fallback both render. */
26
+ /** Two: one with a host and one without, so the card's second line and its
27
+ * letter fallback are both rendered rules. */
27
28
  const SOURCES = [
28
- { id: 'a', title: 'hanzo.ai', href: 'https://hanzo.ai' },
29
- { id: 'b', title: 'Reference' },
29
+ { id: 'a', title: 'The one chat surface', href: 'https://hanzo.ai', host: 'hanzo.ai' },
30
+ { id: 'b', title: 'A reference with a title long enough to reach the three-line clamp' },
30
31
  ];
31
32
  /** One section. Plain CSS on a plain div — the gallery is a harness, and laying
32
33
  * it out with the components under test would make a layout bug read as a
@@ -50,6 +51,6 @@ export const Gallery = () => (_jsxs("div", { style: { display: 'flex', flexDirec
50
51
  tabs: [
51
52
  { id: 'console', title: 'Console', closable: false, content: _jsx(CardTitle, { children: "console" }) },
52
53
  ],
53
- }, children: _jsx(CardTitle, { children: "center" }) }) }) }), _jsxs(Section, { name: "product-arrangements", children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 320 }, children: [_jsx(Skeleton, { width: 120 }), _jsx(Skeleton, { width: "100%", height: 72, rounded: "$4" }), _jsx(Skeleton.Text, { lines: 3 })] }), _jsx(TooltipAnchor, { description: "Delete this agent", children: _jsx(Button, { children: "hinted" }) }), _jsx(Dialog, { open: true, children: _jsx(DialogTemplate, { title: "Delete agent", description: "This removes every run recorded against it.", confirm: { label: 'Delete', tone: 'danger' }, children: _jsx(CardTitle, { children: "body" }) }) })] }), _jsxs(Section, { name: "chat", children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 520, height: 320 }, children: [_jsxs(ChatHeader, { title: "A conversation with a long enough name to clamp", children: [_jsx(ShareButton, {}), _jsx(AsideToggle, {})] }), _jsxs(Thread, { children: [_jsx(Message, { role: "user", children: "ask" }), _jsxs(Message, { role: "assistant", icon: _jsx(Spinner, {}), actions: _jsx(Badge, { children: "copy" }), children: [_jsx(Step, { name: "shell", status: "running", detail: "git status --porcelain" }), _jsx(Step, { name: "write", status: "done", detail: "src/index.ts", defaultOpen: true, children: _jsx(Code, { language: "json", value: "{}", children: '{}' }) }), _jsx(Step, { name: "fetch", status: "error", detail: "timed out", children: "plain body" }), _jsx(Step, { name: "plan", status: "cancelled" }), _jsx(Code, { language: "typescript", value: "const x = 1", children: "const x = 1" }), _jsx(Sources, { sources: SOURCES })] }), _jsx(Message, { role: "assistant", busy: true, children: "answering" }), _jsx(Message, { role: "assistant", children: _jsx(Failure, { onRetry: NOOP, children: "The model stopped before finishing." }) }), _jsx(Message, { role: "assistant", children: _jsx(Failure, { children: "Rate limited." }) }), _jsx(Message, { role: "system", children: "note" })] }), _jsx(Composer, { value: "a draft", onChange: NOOP, onSend: NOOP, hint: "Enter to send", children: _jsx(Badge, { children: "tool" }) }), _jsx(Composer, { value: "", onChange: NOOP, onSend: NOOP, onStop: NOOP, busy: true })] }), _jsx(Aside, { children: _jsx(Sources, { sources: SOURCES }) }), _jsx("div", { style: { display: 'flex', width: 260, height: 320 }, children: _jsxs(Sidebar, { children: [_jsx(SidebarHeader, { title: "Hanzo", onOpenSwitcher: NOOP, onSearch: NOOP, onCollapse: NOOP }), _jsx(SidebarNewChat, { onPress: NOOP }), _jsxs(SidebarScroll, { children: [_jsxs(SidebarSection, { label: "Today", children: [_jsx(SidebarItem, { active: true, onPress: NOOP, children: "Selected thread" }), _jsx(SidebarItem, { onPress: NOOP, children: "Another thread" })] }), _jsx(SidebarFolder, { name: "Archive", defaultOpen: true, children: _jsx(SidebarItem, { onPress: NOOP, children: "Nested thread" }) })] }), _jsx(SidebarUser, { name: "z", secondary: "z@hanzo.ai", onPress: NOOP, onHelp: NOOP })] }) })] }), _jsxs(Section, { name: "box", children: [_jsx(Box, { className: "flex items-center gap-4 px-6 py-3 rounded-lg border", children: _jsx(CardTitle, { children: "utility classes" }) }), _jsx(Box, { className: "flex-col gap-2 max-w-3xl mx-auto overflow-hidden", children: _jsx(CardTitle, { children: "column" }) })] })] }));
54
+ }, children: _jsx(CardTitle, { children: "center" }) }) }) }), _jsxs(Section, { name: "product-arrangements", children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 320 }, children: [_jsx(Skeleton, { width: 120 }), _jsx(Skeleton, { width: "100%", height: 72, rounded: "$4" }), _jsx(Skeleton.Text, { lines: 3 })] }), _jsx(TooltipAnchor, { description: "Delete this agent", children: _jsx(Button, { children: "hinted" }) }), _jsx(Dialog, { open: true, children: _jsx(DialogTemplate, { title: "Delete agent", description: "This removes every run recorded against it.", confirm: { label: 'Delete', tone: 'danger' }, children: _jsx(CardTitle, { children: "body" }) }) })] }), _jsxs(Section, { name: "chat", children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 12, width: 520, height: 320 }, children: [_jsxs(ChatHeader, { title: "A conversation with a long enough name to clamp", leading: _jsx(AsideToggle, {}), onOpenMenu: NOOP, children: [_jsx(ShareButton, {}), _jsx(AsideToggle, {})] }), _jsxs(Thread, { children: [_jsx(Message, { role: "user", children: "ask" }), _jsxs(Message, { role: "assistant", icon: _jsx(Spinner, {}), actions: _jsx(Badge, { children: "copy" }), children: [_jsx(Step, { name: "shell", status: "running", detail: "git status --porcelain" }), _jsx(Step, { name: "write", status: "done", detail: "src/index.ts", defaultOpen: true, children: _jsx(Code, { language: "json", value: "{}", children: '{}' }) }), _jsx(Step, { name: "fetch", status: "error", detail: "timed out", children: "plain body" }), _jsx(Step, { name: "plan", status: "cancelled" }), _jsx(Code, { language: "typescript", value: "const x = 1", children: "const x = 1" }), _jsx(Sources, { sources: SOURCES })] }), _jsx(Message, { role: "assistant", busy: true, children: "answering" }), _jsx(Message, { role: "assistant", children: _jsx(Failure, { onRetry: NOOP, children: "The model stopped before finishing." }) }), _jsx(Message, { role: "assistant", children: _jsx(Failure, { children: "Rate limited." }) }), _jsx(Message, { role: "user", body: { bg: '$color5', rounded: '$3' }, children: "restyled bubble" }), _jsx(Message, { role: "system", children: "note" })] }), _jsx(Composer, { value: "a draft", onChange: NOOP, onSend: NOOP, hint: "Enter to send", children: _jsx(Badge, { children: "tool" }) }), _jsx(Composer, { value: "", onChange: NOOP, onSend: NOOP, onStop: NOOP, busy: true })] }), _jsx(Aside, { children: _jsx(Sources, { sources: SOURCES }) }), _jsx("div", { style: { display: 'flex', width: 260, height: 320 }, children: _jsxs(Sidebar, { children: [_jsx(SidebarHeader, { title: "Hanzo", onOpenSwitcher: NOOP, onSearch: NOOP, onCollapse: NOOP }), _jsx(SidebarNewChat, { onPress: NOOP }), _jsxs(SidebarScroll, { children: [_jsxs(SidebarSection, { label: "Today", children: [_jsx(SidebarItem, { active: true, onPress: NOOP, children: "Selected thread" }), _jsx(SidebarItem, { onPress: NOOP, children: "Another thread" })] }), _jsx(SidebarFolder, { name: "Archive", defaultOpen: true, children: _jsx(SidebarItem, { onPress: NOOP, children: "Nested thread" }) })] }), _jsx(SidebarUser, { name: "z", secondary: "z@hanzo.ai", onPress: NOOP, onHelp: NOOP })] }) })] }), _jsxs(Section, { name: "box", children: [_jsx(Box, { className: "flex items-center gap-4 px-6 py-3 rounded-lg border", children: _jsx(CardTitle, { children: "utility classes" }) }), _jsx(Box, { className: "flex-col gap-2 max-w-3xl mx-auto overflow-hidden", children: _jsx(CardTitle, { children: "column" }) })] })] }));
54
55
  export default Gallery;
55
56
  //# sourceMappingURL=gallery.js.map