@hanzo/ui 8.4.3 → 8.4.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.
package/dist/box.cjs CHANGED
@@ -21,6 +21,20 @@ const jsx_runtime_1 = require("react/jsx-runtime");
21
21
  * 77 of 225 elements on one page into flex containers that were never asked to
22
22
  * be: an inline run became a column, a heading's width collapsed to its text,
23
23
  * and a page grew 8% taller.
24
+ *
25
+ * `tag` renders the element Box is standing in for, and it is what makes the
26
+ * migration reach past `<div>`. Divs are about a third of what carries a
27
+ * className in these apps; the rest are `p`, `span`, `li`, `h2`, `section`, `a`.
28
+ * Converting those to a div-only Box would read as a rename and would in fact
29
+ * strip the document of its headings, lists and paragraphs — every one of them a
30
+ * thing a screen reader navigates by.
31
+ *
32
+ * It goes through `asChild` because gui does NOT honour a `tag` prop: asked for
33
+ * one it renders its own element anyway AND passes `tag` through to the DOM,
34
+ * where it is an invalid attribute. `asChild` is the supported way to say "style
35
+ * this element instead of yours", so the semantics come from the element and the
36
+ * styling still comes from gui — one substrate, not a second styling path for
37
+ * everything that is not a div.
24
38
  */
25
39
  const react_1 = require("react");
26
40
  const gui_1 = require("@hanzo/gui");
@@ -29,7 +43,7 @@ const tw_1 = require("./tw.cjs");
29
43
  const TEXT_PROPS = ['fontSize', 'lineHeight', 'fontWeight', 'letterSpacing',
30
44
  'textTransform', 'fontFamily', 'fontStyle', 'textAlign', 'color',
31
45
  'textDecorationLine', 'whiteSpace'];
32
- exports.Box = (0, react_1.forwardRef)(function Box({ className, children, 'aria-hidden': hidden, ...rest }, ref) {
46
+ exports.Box = (0, react_1.forwardRef)(function Box({ className, children, 'aria-hidden': hidden, tag, ...rest }, ref) {
33
47
  const { props, rest: unread } = (0, tw_1.tw)(className);
34
48
  // A View pins `min-height: 0`; a div's is `auto`, and auto is what gives a
35
49
  // flex or grid child its automatic minimum size. Pinned, a converted child of
@@ -52,15 +66,21 @@ exports.Box = (0, react_1.forwardRef)(function Box({ className, children, 'aria-
52
66
  // class said otherwise, so `leading-relaxed` still wins.
53
67
  if (!('lineHeight' in text))
54
68
  text.lineHeight = 'inherit';
69
+ const style = Object.keys(text).length
70
+ ? { ...text, ...rest.style }
71
+ : rest.style;
55
72
  // Explicit props win: a caller who states a value directly means it, and the
56
73
  // classes are what they are migrating away from.
57
- return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ref: ref, display: "block",
74
+ const frame = ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ref: tag ? undefined : ref, asChild: tag ? true : undefined, display: "block",
58
75
  // A View does not shrink; a div does. Left at the View's default, every
59
76
  // converted flex child held its full basis and overflowed its row instead
60
77
  // of sharing it — two half-width columns came out 608px each in a 1216px
61
78
  // row with a 32px gap, where the divs they replaced sat at 592.
62
79
  // `shrink`, not `flexShrink`: gui types the shorthand and compiles both to
63
80
  // the same `_shrink-1`, and the DOM spelling is the one it does not carry.
64
- shrink: 1, "aria-hidden": hidden === undefined ? undefined : hidden !== 'false' && hidden !== false, ...props, ...rest, className: unread || undefined, style: Object.keys(text).length ? { ...text, ...rest.style } : rest.style, children: children }));
81
+ shrink: 1, "aria-hidden": hidden === undefined ? undefined : hidden !== 'false' && hidden !== false, ...props, ...rest, className: tag ? undefined : unread || undefined, style: tag ? undefined : style, children: tag
82
+ ? (0, react_1.createElement)(tag, { ref, className: unread || undefined, style }, children)
83
+ : children }));
84
+ return frame;
65
85
  });
66
86
  exports.default = exports.Box;
package/dist/box.d.ts CHANGED
@@ -16,6 +16,20 @@
16
16
  * 77 of 225 elements on one page into flex containers that were never asked to
17
17
  * be: an inline run became a column, a heading's width collapsed to its text,
18
18
  * and a page grew 8% taller.
19
+ *
20
+ * `tag` renders the element Box is standing in for, and it is what makes the
21
+ * migration reach past `<div>`. Divs are about a third of what carries a
22
+ * className in these apps; the rest are `p`, `span`, `li`, `h2`, `section`, `a`.
23
+ * Converting those to a div-only Box would read as a rename and would in fact
24
+ * strip the document of its headings, lists and paragraphs — every one of them a
25
+ * thing a screen reader navigates by.
26
+ *
27
+ * It goes through `asChild` because gui does NOT honour a `tag` prop: asked for
28
+ * one it renders its own element anyway AND passes `tag` through to the DOM,
29
+ * where it is an invalid attribute. `asChild` is the supported way to say "style
30
+ * this element instead of yours", so the semantics come from the element and the
31
+ * styling still comes from gui — one substrate, not a second styling path for
32
+ * everything that is not a div.
19
33
  */
20
34
  import { type ReactNode } from 'react';
21
35
  import { YStack } from '@hanzo/gui';
@@ -23,6 +37,10 @@ import { type ClassValue } from './tw.js';
23
37
  export type BoxProps = Omit<React.ComponentProps<typeof YStack>, 'aria-hidden'> & {
24
38
  className?: ClassValue;
25
39
  children?: ReactNode;
40
+ /**
41
+ * The element to render. Omitted, Box is the `<div>` it has always been.
42
+ */
43
+ tag?: keyof React.JSX.IntrinsicElements;
26
44
  /**
27
45
  * ARIA states are strings in markup and gui types this one as a boolean, so
28
46
  * both spellings are taken and normalised. Rejecting `"true"` would make a
package/dist/box.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../src/box.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAM,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAO1C,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,aAAa,CAAC,GAAG;IAChF,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;CAC3C,CAAA;AAED,eAAO,MAAM,GAAG,uGA0Cd,CAAA;eAEa,GAAG"}
1
+ {"version":3,"file":"box.d.ts","sourceRoot":"","sources":["../src/box.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAM,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAO1C,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,aAAa,CAAC,GAAG;IAChF,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAA;IACvC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;CAC3C,CAAA;AAED,eAAO,MAAM,GAAG,uGAqDd,CAAA;eAEa,GAAG"}
package/dist/box.js CHANGED
@@ -18,15 +18,29 @@ import { jsx as _jsx } from "react/jsx-runtime";
18
18
  * 77 of 225 elements on one page into flex containers that were never asked to
19
19
  * be: an inline run became a column, a heading's width collapsed to its text,
20
20
  * and a page grew 8% taller.
21
+ *
22
+ * `tag` renders the element Box is standing in for, and it is what makes the
23
+ * migration reach past `<div>`. Divs are about a third of what carries a
24
+ * className in these apps; the rest are `p`, `span`, `li`, `h2`, `section`, `a`.
25
+ * Converting those to a div-only Box would read as a rename and would in fact
26
+ * strip the document of its headings, lists and paragraphs — every one of them a
27
+ * thing a screen reader navigates by.
28
+ *
29
+ * It goes through `asChild` because gui does NOT honour a `tag` prop: asked for
30
+ * one it renders its own element anyway AND passes `tag` through to the DOM,
31
+ * where it is an invalid attribute. `asChild` is the supported way to say "style
32
+ * this element instead of yours", so the semantics come from the element and the
33
+ * styling still comes from gui — one substrate, not a second styling path for
34
+ * everything that is not a div.
21
35
  */
22
- import { forwardRef } from 'react';
36
+ import { createElement, forwardRef } from 'react';
23
37
  import { YStack } from '@hanzo/gui';
24
38
  import { tw } from './tw.js';
25
39
  /** Properties a frame ignores and a DOM element passes to its children. */
26
40
  const TEXT_PROPS = ['fontSize', 'lineHeight', 'fontWeight', 'letterSpacing',
27
41
  'textTransform', 'fontFamily', 'fontStyle', 'textAlign', 'color',
28
42
  'textDecorationLine', 'whiteSpace'];
29
- export const Box = forwardRef(function Box({ className, children, 'aria-hidden': hidden, ...rest }, ref) {
43
+ export const Box = forwardRef(function Box({ className, children, 'aria-hidden': hidden, tag, ...rest }, ref) {
30
44
  const { props, rest: unread } = tw(className);
31
45
  // A View pins `min-height: 0`; a div's is `auto`, and auto is what gives a
32
46
  // flex or grid child its automatic minimum size. Pinned, a converted child of
@@ -49,16 +63,22 @@ export const Box = forwardRef(function Box({ className, children, 'aria-hidden':
49
63
  // class said otherwise, so `leading-relaxed` still wins.
50
64
  if (!('lineHeight' in text))
51
65
  text.lineHeight = 'inherit';
66
+ const style = Object.keys(text).length
67
+ ? { ...text, ...rest.style }
68
+ : rest.style;
52
69
  // Explicit props win: a caller who states a value directly means it, and the
53
70
  // classes are what they are migrating away from.
54
- return (_jsx(YStack, { ref: ref, display: "block",
71
+ const frame = (_jsx(YStack, { ref: tag ? undefined : ref, asChild: tag ? true : undefined, display: "block",
55
72
  // A View does not shrink; a div does. Left at the View's default, every
56
73
  // converted flex child held its full basis and overflowed its row instead
57
74
  // of sharing it — two half-width columns came out 608px each in a 1216px
58
75
  // row with a 32px gap, where the divs they replaced sat at 592.
59
76
  // `shrink`, not `flexShrink`: gui types the shorthand and compiles both to
60
77
  // the same `_shrink-1`, and the DOM spelling is the one it does not carry.
61
- shrink: 1, "aria-hidden": hidden === undefined ? undefined : hidden !== 'false' && hidden !== false, ...props, ...rest, className: unread || undefined, style: Object.keys(text).length ? { ...text, ...rest.style } : rest.style, children: children }));
78
+ shrink: 1, "aria-hidden": hidden === undefined ? undefined : hidden !== 'false' && hidden !== false, ...props, ...rest, className: tag ? undefined : unread || undefined, style: tag ? undefined : style, children: tag
79
+ ? createElement(tag, { ref, className: unread || undefined, style }, children)
80
+ : children }));
81
+ return frame;
62
82
  });
63
83
  export default Box;
64
84
  //# sourceMappingURL=box.js.map
package/dist/box.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"box.js","sourceRoot":"","sources":["../src/box.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,EAAE,EAAmB,MAAM,MAAM,CAAA;AAE1C,2EAA2E;AAC3E,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe;IACzE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO;IAChE,oBAAoB,EAAE,YAAY,CAAU,CAAA;AAa9C,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAgB,SAAS,GAAG,CACvD,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EACvD,GAAG;IAEH,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAC7C,2EAA2E;IAC3E,8EAA8E;IAC9E,oEAAoE;IACpE,IAAI,CAAC,CAAC,WAAW,IAAI,KAAK,CAAC;QAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAA;IACrD,6EAA6E;IAC7E,0EAA0E;IAC1E,8EAA8E;IAC9E,0EAA0E;IAC1E,yBAAyB;IACzB,MAAM,IAAI,GAA4B,EAAE,CAAA;IACxC,KAAK,MAAM,CAAC,IAAI,UAAU;QAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;QAAC,CAAC;IACnF,6EAA6E;IAC7E,0EAA0E;IAC1E,yDAAyD;IACzD,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC;QAAE,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;IACxD,6EAA6E;IAC7E,iDAAiD;IACjD,OAAO,CACL,KAAC,MAAM,IACL,GAAG,EAAE,GAAG,EACR,OAAO,EAAC,OAAO;QACf,wEAAwE;QACxE,0EAA0E;QAC1E,yEAAyE;QACzE,gEAAgE;QAChE,2EAA2E;QAC3E,2EAA2E;QAC3E,MAAM,EAAE,CAAC,iBACI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK,KACjF,KAAgB,KACjB,IAAI,EACR,SAAS,EAAE,MAAM,IAAI,SAAS,EAC9B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAI,IAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAE,IAAY,CAAC,KAAK,YAE1F,QAAQ,GACF,CACV,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,GAAG,CAAA"}
1
+ {"version":3,"file":"box.js","sourceRoot":"","sources":["../src/box.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,EAAE,EAAmB,MAAM,MAAM,CAAA;AAE1C,2EAA2E;AAC3E,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe;IACzE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO;IAChE,oBAAoB,EAAE,YAAY,CAAU,CAAA;AAiB9C,MAAM,CAAC,MAAM,GAAG,GAAG,UAAU,CAAgB,SAAS,GAAG,CACvD,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,EAC5D,GAAG;IAEH,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAC7C,2EAA2E;IAC3E,8EAA8E;IAC9E,oEAAoE;IACpE,IAAI,CAAC,CAAC,WAAW,IAAI,KAAK,CAAC;QAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAA;IACrD,6EAA6E;IAC7E,0EAA0E;IAC1E,8EAA8E;IAC9E,0EAA0E;IAC1E,yBAAyB;IACzB,MAAM,IAAI,GAA4B,EAAE,CAAA;IACxC,KAAK,MAAM,CAAC,IAAI,UAAU;QAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;QAAC,CAAC;IACnF,6EAA6E;IAC7E,0EAA0E;IAC1E,yDAAyD;IACzD,IAAI,CAAC,CAAC,YAAY,IAAI,IAAI,CAAC;QAAE,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;IACxD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM;QACpC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAI,IAAY,CAAC,KAAK,EAAE;QACrC,CAAC,CAAE,IAAY,CAAC,KAAK,CAAA;IACvB,6EAA6E;IAC7E,iDAAiD;IACjD,MAAM,KAAK,GAAG,CACZ,KAAC,MAAM,IACL,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAC1B,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAC/B,OAAO,EAAC,OAAO;QACf,wEAAwE;QACxE,0EAA0E;QAC1E,yEAAyE;QACzE,gEAAgE;QAChE,2EAA2E;QAC3E,2EAA2E;QAC3E,MAAM,EAAE,CAAC,iBACI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK,KACjF,KAAgB,KACjB,IAAI,EACR,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,SAAS,EAChD,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,YAK7B,GAAG;YACF,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,IAAI,SAAS,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC;YAC9E,CAAC,CAAC,QAAQ,GACL,CACV,CAAA;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAC,CAAA;AAEF,eAAe,GAAG,CAAA"}
@@ -39,6 +39,7 @@ const slot_1 = require("../backends/gui/slot.cjs");
39
39
  const Composer_1 = require("./Composer.cjs");
40
40
  const Message_1 = require("./Message.cjs");
41
41
  const Thread_1 = require("./Thread.cjs");
42
+ const words_1 = require("./words.cjs");
42
43
  function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, composer, ...thread }) {
43
44
  const [draft, setDraft] = (0, react_1.useState)('');
44
45
  // Clearing here rather than in an effect on `messages` is what keeps a send
@@ -62,5 +63,5 @@ function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, e
62
63
  // from the composer lands on a `display: contents` wrapper or on the page,
63
64
  // and then reports a component that is fine as broken, or one that is broken
64
65
  // as fine.
65
- 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)(turn.content ?? '') }, turn.id))) })), (0, jsx_runtime_1.jsx)(Composer_1.Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer })] }));
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 })] }));
66
67
  }
@@ -2,6 +2,7 @@ import { type ReactNode } from 'react';
2
2
  import { type ComposerProps } from './Composer.js';
3
3
  import { type Role } from './Message.js';
4
4
  import { type ThreadProps } from './Thread.js';
5
+ import { type Said } from './words.js';
5
6
  /**
6
7
  * One turn, as little of it as a picture needs: who spoke, what they said, and
7
8
  * an identity to key the list on.
@@ -13,7 +14,16 @@ import { type ThreadProps } from './Thread.js';
13
14
  export interface Turn {
14
15
  id: string;
15
16
  role: Role;
16
- content?: string;
17
+ /**
18
+ * What was said — a string, or the wire's parts.
19
+ *
20
+ * This was `string` alone, which is the same mistake `Role` made one field
21
+ * over: a completion's content is `string | ContentPart[]` (text beside an
22
+ * image), so a turn holding an attachment could not be handed to this at all.
23
+ * Narrowing the wire in a component fed BY the wire just relocates the
24
+ * mismatch to every caller. `words` is the flattener.
25
+ */
26
+ content?: Said;
17
27
  }
18
28
  export interface ChatProps extends Omit<ThreadProps, 'children' | 'ref'> {
19
29
  /** The conversation, oldest first. */
@@ -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;AAEnD;;;;;;;GAOG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;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,2CAoDX"}
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,2CAoDX"}
package/dist/chat/Chat.js CHANGED
@@ -36,6 +36,7 @@ import { slot } from '../backends/gui/slot.js';
36
36
  import { Composer } from './Composer.js';
37
37
  import { Message } from './Message.js';
38
38
  import { Thread } from './Thread.js';
39
+ import { words } from './words.js';
39
40
  export function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, composer, ...thread }) {
40
41
  const [draft, setDraft] = useState('');
41
42
  // Clearing here rather than in an effect on `messages` is what keeps a send
@@ -59,6 +60,6 @@ export function Chat({ messages, streaming = false, send: onSend, stop: onStop,
59
60
  // from the composer lands on a `display: contents` wrapper or on the page,
60
61
  // and then reports a component that is fine as broken, or one that is broken
61
62
  // as fine.
62
- 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(turn.content ?? '') }, turn.id))) })), _jsx(Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer })] }));
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 })] }));
63
64
  }
64
65
  //# 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;AAkDnD,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,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,IAJvC,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,6 +1,6 @@
1
1
  'use client';"use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
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 = exports.Chat = 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 = exports.words = exports.Chat = void 0;
4
4
  /**
5
5
  * @hanzo/ui/chat — the one chat shell, on @hanzo/gui primitives.
6
6
  *
@@ -33,6 +33,8 @@ exports.SourceCard = exports.Sources = exports.Failure = exports.Step = exports.
33
33
  */
34
34
  var Chat_1 = require("./Chat.cjs");
35
35
  Object.defineProperty(exports, "Chat", { enumerable: true, get: function () { return Chat_1.Chat; } });
36
+ var words_1 = require("./words.cjs");
37
+ Object.defineProperty(exports, "words", { enumerable: true, get: function () { return words_1.words; } });
36
38
  var Composer_1 = require("./Composer.cjs");
37
39
  Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return Composer_1.Composer; } });
38
40
  Object.defineProperty(exports, "ASK", { enumerable: true, get: function () { return Composer_1.ASK; } });
@@ -29,6 +29,7 @@
29
29
  * copy button looks in a chat module.
30
30
  */
31
31
  export { Chat, type ChatProps, type Turn } from './Chat.js';
32
+ export { words, type Part, type Said } from './words.js';
32
33
  export { Composer, ASK, type ComposerProps } from './Composer.js';
33
34
  export { Caret, Message, type MessageProps, type Role } from './Message.js';
34
35
  export { Thread, type ThreadProps } from './Thread.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AACxD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AACxD,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAA;AACrD,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"}
@@ -29,6 +29,7 @@
29
29
  * copy button looks in a chat module.
30
30
  */
31
31
  export { Chat } from './Chat.js';
32
+ export { words } from './words.js';
32
33
  export { Composer, ASK } from './Composer.js';
33
34
  export { Caret, Message } from './Message.js';
34
35
  export { Thread } from './Thread.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,IAAI,EAA6B,MAAM,QAAQ,CAAA;AACxD,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,IAAI,EAA6B,MAAM,QAAQ,CAAA;AACxD,OAAO,EAAE,KAAK,EAAwB,MAAM,SAAS,CAAA;AACrD,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"}
@@ -5,12 +5,12 @@
5
5
  // spec, and in a server component. `@hanzo/ui/chat` cannot: it is TSX behind a
6
6
  // client directive.
7
7
  //
8
- // import { sends, ready, pinned, SLACK } from '@hanzo/ui/chat/pure'
8
+ // import { sends, ready, pinned, SLACK, words } from '@hanzo/ui/chat/pure'
9
9
  //
10
10
  // `@hanzo/ui/product/pure` re-exports all four, because none of them is a chat
11
11
  // rule and that is the entry point a non-chat surface imports them from.
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.SLACK = exports.pinned = exports.sends = exports.ready = void 0;
13
+ exports.words = exports.SLACK = exports.pinned = exports.sends = exports.ready = void 0;
14
14
  // Enter, and whether a draft may go. Read `sends` before writing another one:
15
15
  // the IME guard is the point.
16
16
  var send_1 = require("./send.cjs");
@@ -20,3 +20,6 @@ Object.defineProperty(exports, "sends", { enumerable: true, get: function () { r
20
20
  var stick_1 = require("./stick.cjs");
21
21
  Object.defineProperty(exports, "pinned", { enumerable: true, get: function () { return stick_1.pinned; } });
22
22
  Object.defineProperty(exports, "SLACK", { enumerable: true, get: function () { return stick_1.SLACK; } });
23
+ // The text of a turn whose content may be a string or the wire's parts.
24
+ var words_1 = require("./words.cjs");
25
+ Object.defineProperty(exports, "words", { enumerable: true, get: function () { return words_1.words; } });
@@ -1,3 +1,4 @@
1
1
  export { ready, sends, type Mods } from './send.js';
2
2
  export { pinned, SLACK, type Track } from './stick.js';
3
+ export { words, type Part, type Said } from './words.js';
3
4
  //# sourceMappingURL=pure.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pure.d.ts","sourceRoot":"","sources":["../../src/chat/pure.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAGhD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"pure.d.ts","sourceRoot":"","sources":["../../src/chat/pure.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAGhD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAGnD,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,KAAK,IAAI,EAAE,MAAM,SAAS,CAAA"}
package/dist/chat/pure.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // spec, and in a server component. `@hanzo/ui/chat` cannot: it is TSX behind a
5
5
  // client directive.
6
6
  //
7
- // import { sends, ready, pinned, SLACK } from '@hanzo/ui/chat/pure'
7
+ // import { sends, ready, pinned, SLACK, words } from '@hanzo/ui/chat/pure'
8
8
  //
9
9
  // `@hanzo/ui/product/pure` re-exports all four, because none of them is a chat
10
10
  // rule and that is the entry point a non-chat surface imports them from.
@@ -13,4 +13,6 @@
13
13
  export { ready, sends } from './send.js';
14
14
  // Stay-at-the-bottom, as a distance test.
15
15
  export { pinned, SLACK } from './stick.js';
16
+ // The text of a turn whose content may be a string or the wire's parts.
17
+ export { words } from './words.js';
16
18
  //# sourceMappingURL=pure.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pure.js","sourceRoot":"","sources":["../../src/chat/pure.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,oBAAoB;AACpB,EAAE;AACF,sEAAsE;AACtE,EAAE;AACF,+EAA+E;AAC/E,yEAAyE;AAEzE,8EAA8E;AAC9E,8BAA8B;AAC9B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAa,MAAM,QAAQ,CAAA;AAEhD,0CAA0C;AAC1C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"pure.js","sourceRoot":"","sources":["../../src/chat/pure.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,oBAAoB;AACpB,EAAE;AACF,6EAA6E;AAC7E,EAAE;AACF,+EAA+E;AAC/E,yEAAyE;AAEzE,8EAA8E;AAC9E,8BAA8B;AAC9B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAa,MAAM,QAAQ,CAAA;AAEhD,0CAA0C;AAC1C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,wEAAwE;AACxE,OAAO,EAAE,KAAK,EAAwB,MAAM,SAAS,CAAA"}
@@ -0,0 +1,27 @@
1
+ 'use client';"use strict";
2
+ // What a turn said.
3
+ //
4
+ // A completion's content is a string OR a list of parts — text beside an image
5
+ // — so a component fed by the wire has to accept both, and everything that
6
+ // wants the words has to flatten the second case. Six surfaces wrote that
7
+ // flattener; this is the one.
8
+ //
9
+ // No imports, deliberately: a surface passing `body` to <Chat> needs it before
10
+ // it can hand a turn to a markdown parser, and a spec needs it with no gui.
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.words = words;
13
+ /**
14
+ * The text of a turn, with the non-text parts left out.
15
+ *
16
+ * An image part contributes nothing rather than a placeholder: a caller that
17
+ * wants to draw the attachment reads the parts itself, and one that wants the
18
+ * prose wants the prose. Joined with no separator, because the wire splits a
19
+ * sentence across parts and a space would land inside a word.
20
+ */
21
+ function words(said) {
22
+ if (typeof said === 'string')
23
+ return said;
24
+ if (!said)
25
+ return '';
26
+ return said.map((p) => p.text ?? '').join('');
27
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A part of a turn.
3
+ *
4
+ * Structural, and it names `@hanzo/ai` nowhere — this package is fetch-free and
5
+ * depends on the SDK for nothing. Describing the shape here is what lets the
6
+ * two compose exactly while neither imports the other. `type` is open because
7
+ * the wire's is: today's set is text and images, and a part this does not know
8
+ * simply carries no text.
9
+ */
10
+ export interface Part {
11
+ type: string;
12
+ text?: string;
13
+ }
14
+ /** What a turn carries: a string, the wire's parts, or nothing yet. */
15
+ export type Said = string | Part[] | undefined;
16
+ /**
17
+ * The text of a turn, with the non-text parts left out.
18
+ *
19
+ * An image part contributes nothing rather than a placeholder: a caller that
20
+ * wants to draw the attachment reads the parts itself, and one that wants the
21
+ * prose wants the prose. Joined with no separator, because the wire splits a
22
+ * sentence across parts and a space would land inside a word.
23
+ */
24
+ export declare function words(said: Said): string;
25
+ //# sourceMappingURL=words.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"words.d.ts","sourceRoot":"","sources":["../../src/chat/words.ts"],"names":[],"mappings":"AAUA;;;;;;;;GAQG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,uEAAuE;AACvE,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,IAAI,EAAE,GAAG,SAAS,CAAA;AAE9C;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAIxC"}
@@ -0,0 +1,25 @@
1
+ 'use client';// What a turn said.
2
+ //
3
+ // A completion's content is a string OR a list of parts — text beside an image
4
+ // — so a component fed by the wire has to accept both, and everything that
5
+ // wants the words has to flatten the second case. Six surfaces wrote that
6
+ // flattener; this is the one.
7
+ //
8
+ // No imports, deliberately: a surface passing `body` to <Chat> needs it before
9
+ // it can hand a turn to a markdown parser, and a spec needs it with no gui.
10
+ /**
11
+ * The text of a turn, with the non-text parts left out.
12
+ *
13
+ * An image part contributes nothing rather than a placeholder: a caller that
14
+ * wants to draw the attachment reads the parts itself, and one that wants the
15
+ * prose wants the prose. Joined with no separator, because the wire splits a
16
+ * sentence across parts and a space would land inside a word.
17
+ */
18
+ export function words(said) {
19
+ if (typeof said === 'string')
20
+ return said;
21
+ if (!said)
22
+ return '';
23
+ return said.map((p) => p.text ?? '').join('');
24
+ }
25
+ //# sourceMappingURL=words.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"words.js","sourceRoot":"","sources":["../../src/chat/words.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,0EAA0E;AAC1E,8BAA8B;AAC9B,EAAE;AACF,+EAA+E;AAC/E,4EAA4E;AAmB5E;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CAAC,IAAU;IAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACzC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAA;IACpB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC/C,CAAC"}
package/dist/gallery.html CHANGED
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.4.3</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
1
+ <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.4.5</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
2
2
  :root { --hanzo-ui-styles: 1; }
3
3
  /* Hanzo Design System — the entry point. Import THIS one file.
4
4
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "8.4.3",
3
+ "version": "8.4.5",
4
4
  "type": "module",
5
5
  "description": "Hanzo UI — the one canonical Hanzo component library, on @hanzo/gui + @hanzo/design. 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": {