@hanzo/ui 8.0.28 → 8.0.32

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 (64) hide show
  1. package/dist/backends/gui/button.d.ts +12 -0
  2. package/dist/backends/gui/button.d.ts.map +1 -1
  3. package/dist/backends/gui/button.js.map +1 -1
  4. package/dist/backends/gui/slot.cjs +11 -1
  5. package/dist/backends/gui/slot.d.ts +9 -0
  6. package/dist/backends/gui/slot.d.ts.map +1 -1
  7. package/dist/backends/gui/slot.js +9 -0
  8. package/dist/backends/gui/slot.js.map +1 -1
  9. package/dist/backends/gui/textarea.cjs +0 -8
  10. package/dist/backends/gui/textarea.d.ts +8 -1
  11. package/dist/backends/gui/textarea.d.ts.map +1 -1
  12. package/dist/backends/gui/textarea.js +0 -8
  13. package/dist/backends/gui/textarea.js.map +1 -1
  14. package/dist/chat/Code.cjs +70 -0
  15. package/dist/chat/Code.d.ts +25 -0
  16. package/dist/chat/Code.d.ts.map +1 -0
  17. package/dist/chat/Code.js +67 -0
  18. package/dist/chat/Code.js.map +1 -0
  19. package/dist/chat/Composer.cjs +56 -0
  20. package/dist/chat/Composer.d.ts +30 -0
  21. package/dist/chat/Composer.d.ts.map +1 -0
  22. package/dist/chat/Composer.js +53 -0
  23. package/dist/chat/Composer.js.map +1 -0
  24. package/dist/chat/Header.cjs +49 -0
  25. package/dist/chat/Header.d.ts +46 -0
  26. package/dist/chat/Header.d.ts.map +1 -0
  27. package/dist/chat/Header.js +43 -0
  28. package/dist/chat/Header.js.map +1 -0
  29. package/dist/chat/Message.cjs +27 -0
  30. package/dist/chat/Message.d.ts +14 -0
  31. package/dist/chat/Message.d.ts.map +1 -0
  32. package/dist/chat/Message.js +25 -0
  33. package/dist/chat/Message.js.map +1 -0
  34. package/dist/chat/Sidebar.cjs +81 -0
  35. package/dist/chat/Sidebar.d.ts +79 -0
  36. package/dist/chat/Sidebar.d.ts.map +1 -0
  37. package/dist/chat/Sidebar.js +71 -0
  38. package/dist/chat/Sidebar.js.map +1 -0
  39. package/dist/chat/Sources.cjs +25 -0
  40. package/dist/chat/Sources.d.ts +23 -0
  41. package/dist/chat/Sources.d.ts.map +1 -0
  42. package/dist/chat/Sources.js +22 -0
  43. package/dist/chat/Sources.js.map +1 -0
  44. package/dist/chat/Thread.cjs +42 -0
  45. package/dist/chat/Thread.d.ts +11 -0
  46. package/dist/chat/Thread.d.ts.map +1 -0
  47. package/dist/chat/Thread.js +40 -0
  48. package/dist/chat/Thread.js.map +1 -0
  49. package/dist/chat/index.cjs +58 -0
  50. package/dist/chat/index.d.ts +30 -0
  51. package/dist/chat/index.d.ts.map +1 -0
  52. package/dist/chat/index.js +30 -0
  53. package/dist/chat/index.js.map +1 -0
  54. package/dist/chat/send.cjs +44 -0
  55. package/dist/chat/send.d.ts +32 -0
  56. package/dist/chat/send.d.ts.map +1 -0
  57. package/dist/chat/send.js +40 -0
  58. package/dist/chat/send.js.map +1 -0
  59. package/dist/chat/stick.cjs +19 -0
  60. package/dist/chat/stick.d.ts +24 -0
  61. package/dist/chat/stick.d.ts.map +1 -0
  62. package/dist/chat/stick.js +16 -0
  63. package/dist/chat/stick.js.map +1 -0
  64. package/package.json +8 -2
@@ -0,0 +1,58 @@
1
+ 'use client';"use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SourceChip = exports.Sources = exports.CopyButton = 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.ASK = exports.Composer = void 0;
4
+ /**
5
+ * @hanzo/ui/chat — the one chat shell, on @hanzo/gui primitives.
6
+ *
7
+ * Shell only: Thread scrolls, Message presents a turn, Composer takes a draft,
8
+ * Sidebar navigates between conversations, Header names the current one, Code
9
+ * and Sources present the two pieces of a turn every surface renders the same
10
+ * way. Content rendering (markdown, tool calls) stays with the surface — they
11
+ * disagree on the pipeline, and none of it is presentational.
12
+ *
13
+ * Everything is props-in, callbacks-out: no transport, no store, no routing, no
14
+ * active-id resolution. The same components serve a live conversation, a shared
15
+ * read-only transcript and a test fixture.
16
+ *
17
+ * Styling is `$` tokens throughout, never literal colours, so each brand retunes
18
+ * through its own theme and nothing here carries a Hanzo mark — which is what
19
+ * lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
20
+ *
21
+ * The model picker is not here: it already ships at `@hanzo/ui/models`, and it
22
+ * is not chat-specific.
23
+ */
24
+ var Composer_1 = require("./Composer.cjs");
25
+ Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return Composer_1.Composer; } });
26
+ Object.defineProperty(exports, "ASK", { enumerable: true, get: function () { return Composer_1.ASK; } });
27
+ var Message_1 = require("./Message.cjs");
28
+ Object.defineProperty(exports, "Message", { enumerable: true, get: function () { return Message_1.Message; } });
29
+ var Thread_1 = require("./Thread.cjs");
30
+ Object.defineProperty(exports, "Thread", { enumerable: true, get: function () { return Thread_1.Thread; } });
31
+ var send_1 = require("./send.cjs");
32
+ Object.defineProperty(exports, "ready", { enumerable: true, get: function () { return send_1.ready; } });
33
+ Object.defineProperty(exports, "sends", { enumerable: true, get: function () { return send_1.sends; } });
34
+ var stick_1 = require("./stick.cjs");
35
+ Object.defineProperty(exports, "pinned", { enumerable: true, get: function () { return stick_1.pinned; } });
36
+ Object.defineProperty(exports, "SLACK", { enumerable: true, get: function () { return stick_1.SLACK; } });
37
+ var Sidebar_1 = require("./Sidebar.cjs");
38
+ Object.defineProperty(exports, "Sidebar", { enumerable: true, get: function () { return Sidebar_1.Sidebar; } });
39
+ Object.defineProperty(exports, "SidebarHeader", { enumerable: true, get: function () { return Sidebar_1.SidebarHeader; } });
40
+ Object.defineProperty(exports, "SidebarIconButton", { enumerable: true, get: function () { return Sidebar_1.SidebarIconButton; } });
41
+ Object.defineProperty(exports, "SidebarNewChat", { enumerable: true, get: function () { return Sidebar_1.SidebarNewChat; } });
42
+ Object.defineProperty(exports, "SidebarScroll", { enumerable: true, get: function () { return Sidebar_1.SidebarScroll; } });
43
+ Object.defineProperty(exports, "SidebarSection", { enumerable: true, get: function () { return Sidebar_1.SidebarSection; } });
44
+ Object.defineProperty(exports, "SidebarItem", { enumerable: true, get: function () { return Sidebar_1.SidebarItem; } });
45
+ Object.defineProperty(exports, "SidebarFolder", { enumerable: true, get: function () { return Sidebar_1.SidebarFolder; } });
46
+ Object.defineProperty(exports, "SidebarUser", { enumerable: true, get: function () { return Sidebar_1.SidebarUser; } });
47
+ var Header_1 = require("./Header.cjs");
48
+ Object.defineProperty(exports, "Header", { enumerable: true, get: function () { return Header_1.Header; } });
49
+ Object.defineProperty(exports, "HeaderButton", { enumerable: true, get: function () { return Header_1.HeaderButton; } });
50
+ Object.defineProperty(exports, "ShareButton", { enumerable: true, get: function () { return Header_1.ShareButton; } });
51
+ Object.defineProperty(exports, "AsideToggle", { enumerable: true, get: function () { return Header_1.AsideToggle; } });
52
+ Object.defineProperty(exports, "Aside", { enumerable: true, get: function () { return Header_1.Aside; } });
53
+ var Code_1 = require("./Code.cjs");
54
+ Object.defineProperty(exports, "Code", { enumerable: true, get: function () { return Code_1.Code; } });
55
+ Object.defineProperty(exports, "CopyButton", { enumerable: true, get: function () { return Code_1.CopyButton; } });
56
+ var Sources_1 = require("./Sources.cjs");
57
+ Object.defineProperty(exports, "Sources", { enumerable: true, get: function () { return Sources_1.Sources; } });
58
+ Object.defineProperty(exports, "SourceChip", { enumerable: true, get: function () { return Sources_1.SourceChip; } });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @hanzo/ui/chat — the one chat shell, on @hanzo/gui primitives.
3
+ *
4
+ * Shell only: Thread scrolls, Message presents a turn, Composer takes a draft,
5
+ * Sidebar navigates between conversations, Header names the current one, Code
6
+ * and Sources present the two pieces of a turn every surface renders the same
7
+ * way. Content rendering (markdown, tool calls) stays with the surface — they
8
+ * disagree on the pipeline, and none of it is presentational.
9
+ *
10
+ * Everything is props-in, callbacks-out: no transport, no store, no routing, no
11
+ * active-id resolution. The same components serve a live conversation, a shared
12
+ * read-only transcript and a test fixture.
13
+ *
14
+ * Styling is `$` tokens throughout, never literal colours, so each brand retunes
15
+ * through its own theme and nothing here carries a Hanzo mark — which is what
16
+ * lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
17
+ *
18
+ * The model picker is not here: it already ships at `@hanzo/ui/models`, and it
19
+ * is not chat-specific.
20
+ */
21
+ export { Composer, ASK, type ComposerProps } from './Composer.js';
22
+ export { Message, type MessageProps, type Role } from './Message.js';
23
+ export { Thread, type ThreadProps } from './Thread.js';
24
+ export { ready, sends, type Mods } from './send.js';
25
+ export { pinned, SLACK, type Track } from './stick.js';
26
+ export { Sidebar, SidebarHeader, SidebarIconButton, SidebarNewChat, SidebarScroll, SidebarSection, SidebarItem, SidebarFolder, SidebarUser, type SidebarProps, type SidebarHeaderProps, type SidebarIconButtonProps, type SidebarNewChatProps, type SidebarSectionProps, type SidebarItemProps, type SidebarFolderProps, type SidebarUserProps, } from './Sidebar.js';
27
+ export { Header, HeaderButton, ShareButton, AsideToggle, Aside, type HeaderProps, type HeaderButtonProps, type ShareButtonProps, type AsideToggleProps, type AsideProps, } from './Header.js';
28
+ export { Code, CopyButton, type CodeProps, type CopyButtonProps } from './Code.js';
29
+ export { Sources, SourceChip, type Source, type SourcesProps, type SourceChipProps, } from './Sources.js';
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AACjE,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,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,QAAQ,CAAA;AAE/E,OAAO,EACL,OAAO,EACP,UAAU,EACV,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAA"}
@@ -0,0 +1,30 @@
1
+ 'use client';/**
2
+ * @hanzo/ui/chat — the one chat shell, on @hanzo/gui primitives.
3
+ *
4
+ * Shell only: Thread scrolls, Message presents a turn, Composer takes a draft,
5
+ * Sidebar navigates between conversations, Header names the current one, Code
6
+ * and Sources present the two pieces of a turn every surface renders the same
7
+ * way. Content rendering (markdown, tool calls) stays with the surface — they
8
+ * disagree on the pipeline, and none of it is presentational.
9
+ *
10
+ * Everything is props-in, callbacks-out: no transport, no store, no routing, no
11
+ * active-id resolution. The same components serve a live conversation, a shared
12
+ * read-only transcript and a test fixture.
13
+ *
14
+ * Styling is `$` tokens throughout, never literal colours, so each brand retunes
15
+ * through its own theme and nothing here carries a Hanzo mark — which is what
16
+ * lets the same shell ship on Lux and Zoo surfaces without leaking a brand.
17
+ *
18
+ * The model picker is not here: it already ships at `@hanzo/ui/models`, and it
19
+ * is not chat-specific.
20
+ */
21
+ export { Composer, ASK } from './Composer.js';
22
+ export { Message } from './Message.js';
23
+ export { Thread } from './Thread.js';
24
+ export { ready, sends } from './send.js';
25
+ export { pinned, SLACK } from './stick.js';
26
+ export { Sidebar, SidebarHeader, SidebarIconButton, SidebarNewChat, SidebarScroll, SidebarSection, SidebarItem, SidebarFolder, SidebarUser, } from './Sidebar.js';
27
+ export { Header, HeaderButton, ShareButton, AsideToggle, Aside, } from './Header.js';
28
+ export { Code, CopyButton } from './Code.js';
29
+ export { Sources, SourceChip, } from './Sources.js';
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAsB,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AACjE,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,EAAE,UAAU,EAAwC,MAAM,QAAQ,CAAA;AAE/E,OAAO,EACL,OAAO,EACP,UAAU,GAIX,MAAM,WAAW,CAAA"}
@@ -0,0 +1,44 @@
1
+ 'use client';"use strict";
2
+ /**
3
+ * The two decisions a composer makes, as pure functions.
4
+ *
5
+ * Every Hanzo chat surface had re-implemented both inline, and they had drifted:
6
+ * one sent on a bare Enter while composing an IME candidate (committing a
7
+ * half-typed word), another let a whitespace-only draft through. Keeping them
8
+ * here means the rules are asserted once, without a DOM.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ready = exports.sends = void 0;
12
+ /** The keyCode every browser reports for a keystroke an IME has claimed. */
13
+ const IME = 229;
14
+ /**
15
+ * Whether the IME owns this keystroke, from all three signals browsers use.
16
+ *
17
+ * `isComposing` alone is not enough. Safari does not set it reliably on the
18
+ * keydown that accepts a candidate, and reports the key as `Process` or with
19
+ * only the legacy `keyCode` of 229 — so a composer that trusts `isComposing`
20
+ * by itself still submits a half-typed word out from under a Japanese, Chinese
21
+ * or Korean writer. That is the bug this module exists to end, and it is not
22
+ * ended by checking one flag.
23
+ */
24
+ const claimed = (key, mods) => mods.isComposing === true || key === 'Process' || mods.keyCode === IME;
25
+ /**
26
+ * Enter sends. Shift+Enter writes a newline, so a multi-line draft is always
27
+ * reachable from the keyboard. Cmd/Ctrl+Enter always sends — it is the force-send
28
+ * every surface already taught its users, and it holds even with Shift down.
29
+ * A keystroke the IME has claimed belongs to the IME, never to the composer.
30
+ */
31
+ const sends = (key, mods = {}) => {
32
+ if (key !== 'Enter' || claimed(key, mods))
33
+ return false;
34
+ if (mods.metaKey === true || mods.ctrlKey === true)
35
+ return true;
36
+ return mods.shiftKey !== true && mods.altKey !== true;
37
+ };
38
+ exports.sends = sends;
39
+ /**
40
+ * Whether a draft may be sent: there has to be something other than whitespace,
41
+ * the surface must not already be waiting on a turn, and the field must be live.
42
+ */
43
+ const ready = (value, busy = false, disabled = false) => !busy && !disabled && value.trim().length > 0;
44
+ exports.ready = ready;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The two decisions a composer makes, as pure functions.
3
+ *
4
+ * Every Hanzo chat surface had re-implemented both inline, and they had drifted:
5
+ * one sent on a bare Enter while composing an IME candidate (committing a
6
+ * half-typed word), another let a whitespace-only draft through. Keeping them
7
+ * here means the rules are asserted once, without a DOM.
8
+ */
9
+ /** Modifier state, in the shape web and native events agree on. */
10
+ export interface Mods {
11
+ shiftKey?: boolean;
12
+ altKey?: boolean;
13
+ metaKey?: boolean;
14
+ ctrlKey?: boolean;
15
+ /** `KeyboardEvent.isComposing` — true while an IME candidate window is open. */
16
+ isComposing?: boolean;
17
+ /** Legacy `KeyboardEvent.keyCode`. Read only to recognise Safari's IME. */
18
+ keyCode?: number;
19
+ }
20
+ /**
21
+ * Enter sends. Shift+Enter writes a newline, so a multi-line draft is always
22
+ * reachable from the keyboard. Cmd/Ctrl+Enter always sends — it is the force-send
23
+ * every surface already taught its users, and it holds even with Shift down.
24
+ * A keystroke the IME has claimed belongs to the IME, never to the composer.
25
+ */
26
+ export declare const sends: (key: string, mods?: Mods) => boolean;
27
+ /**
28
+ * Whether a draft may be sent: there has to be something other than whitespace,
29
+ * the surface must not already be waiting on a turn, and the field must be live.
30
+ */
31
+ export declare const ready: (value: string, busy?: boolean, disabled?: boolean) => boolean;
32
+ //# sourceMappingURL=send.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,40 @@
1
+ 'use client';/**
2
+ * The two decisions a composer makes, as pure functions.
3
+ *
4
+ * Every Hanzo chat surface had re-implemented both inline, and they had drifted:
5
+ * one sent on a bare Enter while composing an IME candidate (committing a
6
+ * half-typed word), another let a whitespace-only draft through. Keeping them
7
+ * here means the rules are asserted once, without a DOM.
8
+ */
9
+ /** The keyCode every browser reports for a keystroke an IME has claimed. */
10
+ const IME = 229;
11
+ /**
12
+ * Whether the IME owns this keystroke, from all three signals browsers use.
13
+ *
14
+ * `isComposing` alone is not enough. Safari does not set it reliably on the
15
+ * keydown that accepts a candidate, and reports the key as `Process` or with
16
+ * only the legacy `keyCode` of 229 — so a composer that trusts `isComposing`
17
+ * by itself still submits a half-typed word out from under a Japanese, Chinese
18
+ * or Korean writer. That is the bug this module exists to end, and it is not
19
+ * ended by checking one flag.
20
+ */
21
+ const claimed = (key, mods) => mods.isComposing === true || key === 'Process' || mods.keyCode === IME;
22
+ /**
23
+ * Enter sends. Shift+Enter writes a newline, so a multi-line draft is always
24
+ * reachable from the keyboard. Cmd/Ctrl+Enter always sends — it is the force-send
25
+ * every surface already taught its users, and it holds even with Shift down.
26
+ * A keystroke the IME has claimed belongs to the IME, never to the composer.
27
+ */
28
+ export const sends = (key, mods = {}) => {
29
+ if (key !== 'Enter' || claimed(key, mods))
30
+ return false;
31
+ if (mods.metaKey === true || mods.ctrlKey === true)
32
+ return true;
33
+ return mods.shiftKey !== true && mods.altKey !== true;
34
+ };
35
+ /**
36
+ * Whether a draft may be sent: there has to be something other than whitespace,
37
+ * the surface must not already be waiting on a turn, and the field must be live.
38
+ */
39
+ export const ready = (value, busy = false, disabled = false) => !busy && !disabled && value.trim().length > 0;
40
+ //# sourceMappingURL=send.js.map
@@ -0,0 +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"}
@@ -0,0 +1,19 @@
1
+ 'use client';"use strict";
2
+ /**
3
+ * Stay-at-the-bottom, as a pure decision.
4
+ *
5
+ * A thread should follow a streaming answer, but it must stop following the
6
+ * moment the reader scrolls up to re-read something — otherwise every new token
7
+ * yanks them back down. The rule is a distance test against the bottom, and it
8
+ * is the piece each surface had written slightly differently.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.pinned = exports.SLACK = void 0;
12
+ /** How far from the bottom still counts as "at the bottom", in px. */
13
+ exports.SLACK = 48;
14
+ /**
15
+ * True while the viewport is within `slack` of the end — including the case
16
+ * where the content is shorter than the viewport and there is nothing to scroll.
17
+ */
18
+ const pinned = ({ offset, viewport, content }, slack = exports.SLACK) => content - viewport - offset <= slack;
19
+ exports.pinned = pinned;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Stay-at-the-bottom, as a pure decision.
3
+ *
4
+ * A thread should follow a streaming answer, but it must stop following the
5
+ * moment the reader scrolls up to re-read something — otherwise every new token
6
+ * yanks them back down. The rule is a distance test against the bottom, and it
7
+ * is the piece each surface had written slightly differently.
8
+ */
9
+ /** How far from the bottom still counts as "at the bottom", in px. */
10
+ export declare const SLACK = 48;
11
+ export interface Track {
12
+ /** Scroll offset from the top. */
13
+ offset: number;
14
+ /** Height of the visible viewport. */
15
+ viewport: number;
16
+ /** Height of the full content. */
17
+ content: number;
18
+ }
19
+ /**
20
+ * True while the viewport is within `slack` of the end — including the case
21
+ * where the content is shorter than the viewport and there is nothing to scroll.
22
+ */
23
+ export declare const pinned: ({ offset, viewport, content }: Track, slack?: number) => boolean;
24
+ //# sourceMappingURL=stick.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stick.d.ts","sourceRoot":"","sources":["../../src/chat/stick.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,sEAAsE;AACtE,eAAO,MAAM,KAAK,KAAK,CAAA;AAEvB,MAAM,WAAW,KAAK;IACpB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,GAAI,+BAA+B,KAAK,EAAE,cAAa,KAAG,OACvC,CAAA"}
@@ -0,0 +1,16 @@
1
+ 'use client';/**
2
+ * Stay-at-the-bottom, as a pure decision.
3
+ *
4
+ * A thread should follow a streaming answer, but it must stop following the
5
+ * moment the reader scrolls up to re-read something — otherwise every new token
6
+ * yanks them back down. The rule is a distance test against the bottom, and it
7
+ * is the piece each surface had written slightly differently.
8
+ */
9
+ /** How far from the bottom still counts as "at the bottom", in px. */
10
+ export const SLACK = 48;
11
+ /**
12
+ * True while the viewport is within `slack` of the end — including the case
13
+ * where the content is shorter than the viewport and there is nothing to scroll.
14
+ */
15
+ export const pinned = ({ offset, viewport, content }, slack = SLACK) => content - viewport - offset <= slack;
16
+ //# sourceMappingURL=stick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stick.js","sourceRoot":"","sources":["../../src/chat/stick.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,sEAAsE;AACtE,MAAM,CAAC,MAAM,KAAK,GAAG,EAAE,CAAA;AAWvB;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAS,EAAE,KAAK,GAAG,KAAK,EAAW,EAAE,CACrF,OAAO,GAAG,QAAQ,GAAG,MAAM,IAAI,KAAK,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "8.0.28",
3
+ "version": "8.0.32",
4
4
  "type": "module",
5
5
  "description": "Hanzo UI — the one canonical Hanzo component library, on @hanzo/gui + @hanzo/tokens. ONE substrate: every component renders through @hanzo/gui primitives, so the same import works on web, native (expo) and desktop (Tauri). Self-contained (theme.css), presentational, host-agnostic, clean-room.",
6
6
  "exports": {
@@ -16,6 +16,12 @@
16
16
  "require": "./dist/models/index.cjs",
17
17
  "default": "./dist/models/index.js"
18
18
  },
19
+ "./chat": {
20
+ "types": "./dist/chat/index.d.ts",
21
+ "import": "./dist/chat/index.js",
22
+ "require": "./dist/chat/index.cjs",
23
+ "default": "./dist/chat/index.js"
24
+ },
19
25
  "./core": {
20
26
  "types": "./dist/core/index.d.ts",
21
27
  "import": "./dist/core/index.js",
@@ -197,7 +203,7 @@
197
203
  "react": "^19.0.0",
198
204
  "react-dom": "^19.0.0",
199
205
  "react-native-web": "^0.21.2",
200
- "typescript": "^7.0.2",
206
+ "typescript": "^5.9.3",
201
207
  "vitest": "^4.1.8"
202
208
  },
203
209
  "publishConfig": {