@hanzo/ui 8.29.22 → 8.29.24
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/chat/Composer.cjs +182 -99
- package/dist/chat/Composer.d.ts +110 -81
- package/dist/chat/Composer.d.ts.map +1 -1
- package/dist/chat/Composer.js +184 -101
- package/dist/chat/Composer.js.map +1 -1
- package/dist/chat/Dial.cjs +96 -0
- package/dist/chat/Dial.d.ts +7 -0
- package/dist/chat/Dial.d.ts.map +1 -0
- package/dist/chat/Dial.js +94 -0
- package/dist/chat/Dial.js.map +1 -0
- package/dist/chat/Dictation.cjs +142 -0
- package/dist/chat/Dictation.d.ts +13 -0
- package/dist/chat/Dictation.d.ts.map +1 -0
- package/dist/chat/Dictation.js +140 -0
- package/dist/chat/Dictation.js.map +1 -0
- package/dist/chat/Families.cjs +41 -0
- package/dist/chat/Families.d.ts +3 -0
- package/dist/chat/Families.d.ts.map +1 -0
- package/dist/chat/Families.js +39 -0
- package/dist/chat/Families.js.map +1 -0
- package/dist/chat/Mention.cjs +25 -0
- package/dist/chat/Mention.d.ts +16 -0
- package/dist/chat/Mention.d.ts.map +1 -0
- package/dist/chat/Mention.js +22 -0
- package/dist/chat/Mention.js.map +1 -0
- package/dist/chat/Palette.cjs +22 -0
- package/dist/chat/Palette.d.ts +21 -0
- package/dist/chat/Palette.d.ts.map +1 -0
- package/dist/chat/Palette.js +20 -0
- package/dist/chat/Palette.js.map +1 -0
- package/dist/chat/Plus.cjs +76 -0
- package/dist/chat/Plus.d.ts +49 -0
- package/dist/chat/Plus.d.ts.map +1 -0
- package/dist/chat/Plus.js +74 -0
- package/dist/chat/Plus.js.map +1 -0
- package/dist/chat/Tune.cjs +55 -0
- package/dist/chat/Tune.d.ts +49 -0
- package/dist/chat/Tune.d.ts.map +1 -0
- package/dist/chat/Tune.js +51 -0
- package/dist/chat/Tune.js.map +1 -0
- package/dist/chat/index.cjs +25 -4
- package/dist/chat/index.d.ts +11 -3
- package/dist/chat/index.d.ts.map +1 -1
- package/dist/chat/index.js +10 -2
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/languages.cjs +17 -0
- package/dist/chat/languages.d.ts +11 -0
- package/dist/chat/languages.d.ts.map +1 -0
- package/dist/chat/languages.js +15 -0
- package/dist/chat/languages.js.map +1 -0
- package/dist/chat/pure.cjs +7 -1
- package/dist/chat/pure.d.ts +3 -1
- package/dist/chat/pure.d.ts.map +1 -1
- package/dist/chat/pure.js +4 -0
- package/dist/chat/pure.js.map +1 -1
- package/dist/chat/ring.cjs +9 -0
- package/dist/chat/ring.d.ts +11 -0
- package/dist/chat/ring.d.ts.map +1 -0
- package/dist/chat/ring.js +7 -0
- package/dist/chat/ring.js.map +1 -0
- package/dist/chat/send.cjs +3 -2
- package/dist/chat/send.d.ts +4 -1
- package/dist/chat/send.d.ts.map +1 -1
- package/dist/chat/send.js +3 -2
- package/dist/chat/send.js.map +1 -1
- package/dist/chat/ways.cjs +19 -0
- package/dist/chat/ways.d.ts +11 -0
- package/dist/chat/ways.d.ts.map +1 -0
- package/dist/chat/ways.js +17 -0
- package/dist/chat/ways.js.map +1 -0
- package/dist/gallery.cjs +4 -1
- package/dist/gallery.d.ts.map +1 -1
- package/dist/gallery.html +45 -15
- package/dist/gallery.js +5 -2
- package/dist/gallery.js.map +1 -1
- package/dist/models/ModelPicker.cjs +3 -3
- package/dist/models/ModelPicker.d.ts +6 -1
- package/dist/models/ModelPicker.d.ts.map +1 -1
- package/dist/models/ModelPicker.js +3 -3
- package/dist/models/ModelPicker.js.map +1 -1
- package/dist/models/ModelPickerMenu.cjs +19 -13
- package/dist/models/ModelPickerMenu.d.ts +4 -0
- package/dist/models/ModelPickerMenu.d.ts.map +1 -1
- package/dist/models/ModelPickerMenu.js +19 -13
- package/dist/models/ModelPickerMenu.js.map +1 -1
- package/dist/models/catalog.cjs +7 -0
- package/dist/models/catalog.d.ts +2 -0
- package/dist/models/catalog.d.ts.map +1 -1
- package/dist/models/catalog.js +6 -0
- package/dist/models/catalog.js.map +1 -1
- package/dist/models/index.cjs +2 -1
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +1 -1
- package/dist/models/index.js.map +1 -1
- package/dist/product/BranchSelect.cjs +1 -1
- package/dist/product/BranchSelect.js +1 -1
- package/dist/product/BranchSelect.js.map +1 -1
- package/dist/product/ChipSelect.cjs +60 -11
- package/dist/product/ChipSelect.d.ts +13 -2
- package/dist/product/ChipSelect.d.ts.map +1 -1
- package/dist/product/ChipSelect.js +61 -12
- package/dist/product/ChipSelect.js.map +1 -1
- package/dist/product/RepoSelect.cjs +11 -5
- package/dist/product/RepoSelect.d.ts +6 -2
- package/dist/product/RepoSelect.d.ts.map +1 -1
- package/dist/product/RepoSelect.js +13 -7
- package/dist/product/RepoSelect.js.map +1 -1
- package/dist/product/chipSelect.logic.d.ts +4 -1
- package/dist/product/chipSelect.logic.d.ts.map +1 -1
- package/dist/product/chipSelect.logic.js.map +1 -1
- package/dist/product/index.cjs +3 -3
- package/dist/product/index.d.ts +1 -1
- package/dist/product/index.d.ts.map +1 -1
- package/dist/product/index.js +3 -3
- package/dist/product/index.js.map +1 -1
- package/dist/styles.css +41 -11
- package/package.json +8 -2
package/dist/chat/Composer.cjs
CHANGED
|
@@ -1,131 +1,214 @@
|
|
|
1
1
|
'use client';"use strict";
|
|
2
2
|
'use client';
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.ASK = void 0;
|
|
4
|
+
exports.ROUND = exports.measure = exports.GAP = exports.MEASURE = exports.ASK = void 0;
|
|
5
|
+
exports.useUpload = useUpload;
|
|
5
6
|
exports.Composer = Composer;
|
|
6
|
-
exports.ComposerTool = ComposerTool;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
/**
|
|
9
|
-
* Composer — the one
|
|
9
|
+
* Composer — the one composer every Hanzo surface draws: Chat, Dev, Studio, a
|
|
10
|
+
* room, a reply, a run being steered. A surface hands it slots and defaults and
|
|
11
|
+
* nothing else; the field, the keys, the controls and their look are here once.
|
|
10
12
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* ┌ pills ───────────────────────────────┐ where a run goes, which repository
|
|
14
|
+
* │ the field │
|
|
15
|
+
* │ + carried… children ✦ 🎙 ⬆ │ + menu, what the draft carries,
|
|
16
|
+
* └──────────────────────────────────────┘ commands, dictation, send / stop
|
|
17
|
+
* chips… model effort mode
|
|
15
18
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* surface got subtly different.
|
|
19
|
+
* Above the frame: the surface's `head`, the `/` or `@` list, and the `note`.
|
|
20
|
+
* Under it, one row: the surface's chips, then the model, the effort and the mode.
|
|
19
21
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
+
* THE PERSON'S SETTING (@hanzo/appearance `useComposing`, Settings →
|
|
23
|
+
* Appearance) decides which key sends and whether the chips, the model
|
|
24
|
+
* selector and the mode are drawn, everywhere at once. An axis they left on
|
|
25
|
+
* Auto takes the surface's `defaults`, and the model selector is off until
|
|
26
|
+
* they turn it on.
|
|
22
27
|
*
|
|
23
|
-
*
|
|
24
|
-
* the
|
|
28
|
+
* Its paint is @hanzo/design's: `$` tokens and `--primary`, sized through
|
|
29
|
+
* `--density` (the round controls are @hanzo/composer's `Control`), so text
|
|
30
|
+
* size, density and accent change it with the rest of the product.
|
|
31
|
+
*
|
|
32
|
+
* Its own words are the reader's language (@hanzo/i18n `t`). A host's words —
|
|
33
|
+
* its placeholder, a shelf's rows, a chip's label — are drawn as given.
|
|
25
34
|
*/
|
|
26
35
|
const gui_1 = require("@hanzo/gui");
|
|
36
|
+
const appearance_1 = require("@hanzo/appearance");
|
|
37
|
+
const composer_1 = require("@hanzo/composer");
|
|
38
|
+
const i18n_1 = require("@hanzo/i18n");
|
|
39
|
+
const react_1 = require("@hanzo/i18n/react");
|
|
27
40
|
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
41
|
+
const voice_1 = require("@hanzo/voice");
|
|
42
|
+
const react_2 = require("react");
|
|
28
43
|
const gui_2 = require("../backends/gui/index.cjs");
|
|
29
44
|
const slot_1 = require("../backends/gui/slot.cjs");
|
|
45
|
+
const glass_1 = require("../glass.cjs");
|
|
46
|
+
const Dial_1 = require("./Dial.cjs");
|
|
47
|
+
const Dictation_1 = require("./Dictation.cjs");
|
|
48
|
+
const Mention_1 = require("./Mention.cjs");
|
|
49
|
+
const Palette_1 = require("./Palette.cjs");
|
|
50
|
+
const Plus_1 = require("./Plus.cjs");
|
|
30
51
|
const send_1 = require("./send.cjs");
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
/** How tall the field may grow before it scrolls, px. Uncapped, a long paste
|
|
34
|
-
* pushes the thread off screen; narrower frames pass their own. */
|
|
35
|
-
const CEILING = 200;
|
|
36
|
-
/** Floor for the field, px. `Textarea` defaults to 64, which is three lines of
|
|
37
|
-
* chrome before anything is typed. 44 is the touch-target floor. */
|
|
38
|
-
const FLOOR = 44;
|
|
52
|
+
const ring_1 = require("./ring.cjs");
|
|
53
|
+
const Tune_1 = require("./Tune.cjs");
|
|
39
54
|
/**
|
|
40
|
-
* The
|
|
41
|
-
*
|
|
42
|
-
* is why the send control can be a 28px mark inside a row a thumb already hits.
|
|
55
|
+
* The resting placeholder. It addresses the person rather than the mechanism,
|
|
56
|
+
* and as one constant it never re-announces when the model changes.
|
|
43
57
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
/** The
|
|
48
|
-
|
|
58
|
+
exports.ASK = (0, i18n_1.phrase)('Ask anything');
|
|
59
|
+
/** The reading measure: @hanzo/design's prose width, which Width (appearance) retunes. */
|
|
60
|
+
exports.MEASURE = 'var(--container-prose, 48rem)';
|
|
61
|
+
/** The space between turns, px: one rhythm for every thread. */
|
|
62
|
+
exports.GAP = 20;
|
|
63
|
+
/** The composer's width under a thread: the measure less its 0.75rem gutters, centred, so its edges are the text's. */
|
|
64
|
+
exports.measure = { width: 'calc(100% - 1.5rem)', maxW: `calc(${exports.MEASURE} - 1.5rem)`, mx: 'auto' };
|
|
65
|
+
/** The round controls' box, px, and a phone's, a thumb's width kept small so the frame is a slim glass bar: `+`, the effort, the mic, its chevron and send all take it, so they share one centreline. */
|
|
66
|
+
exports.ROUND = 32;
|
|
67
|
+
const TAP = 36;
|
|
68
|
+
/** The frame's corner, px: 12 on a laptop; on a phone the inset plus a control's radius, so the send's circle and the frame's corner are concentric. */
|
|
69
|
+
const CORNER = 12;
|
|
70
|
+
const CORNER_PHONE = 24;
|
|
71
|
+
/** How tall the field grows before it scrolls, px. */
|
|
72
|
+
const CEILING = 200;
|
|
73
|
+
/** The ink on a filled round: the accent's own foreground. */
|
|
74
|
+
const ON = 'var(--primary-foreground)';
|
|
75
|
+
/** A round control with no ground of its own until it is pointed at. */
|
|
76
|
+
const QUIET = { bg: 'transparent', color: 'var(--foreground)', hoverStyle: { bg: '$hover' } };
|
|
77
|
+
/** Ctrl+U (⌘U) uploads, while a composer with an upload is on the page. */
|
|
78
|
+
function useUpload(upload) {
|
|
79
|
+
const now = (0, react_2.useRef)(upload);
|
|
80
|
+
now.current = upload;
|
|
81
|
+
(0, react_2.useEffect)(() => {
|
|
82
|
+
if (!upload)
|
|
83
|
+
return;
|
|
84
|
+
const key = (e) => {
|
|
85
|
+
if ((e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && e.key.toLowerCase() === 'u') {
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
now.current?.();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
window.addEventListener('keydown', key);
|
|
91
|
+
return () => window.removeEventListener('keydown', key);
|
|
92
|
+
}, [Boolean(upload)]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
93
|
+
}
|
|
94
|
+
/** The modifier state off a keydown, web or native. */
|
|
95
|
+
const modsOf = (e) => ({
|
|
96
|
+
shiftKey: e.shiftKey ?? e.nativeEvent?.shiftKey,
|
|
97
|
+
altKey: e.altKey ?? e.nativeEvent?.altKey,
|
|
98
|
+
metaKey: e.metaKey ?? e.nativeEvent?.metaKey,
|
|
99
|
+
ctrlKey: e.ctrlKey ?? e.nativeEvent?.ctrlKey,
|
|
100
|
+
isComposing: e.isComposing ?? e.nativeEvent?.isComposing,
|
|
101
|
+
// Safari's only honest IME signal on this keydown.
|
|
102
|
+
keyCode: e.keyCode ?? e.nativeEvent?.keyCode,
|
|
103
|
+
});
|
|
49
104
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* the
|
|
54
|
-
* it never has to be recomputed or re-announced when the model or endpoint
|
|
55
|
-
* changes — which is what a model-named placeholder forces a surface to do.
|
|
105
|
+
* How far the software keyboard covers the page, px: the layout viewport less the
|
|
106
|
+
* visual one. A phone keyboard that does not shrink the layout leaves a fixed
|
|
107
|
+
* composer under it; this is how far to lift it. Zero where the layout follows the
|
|
108
|
+
* keyboard (the browser resized it) and wherever there is no keyboard.
|
|
56
109
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
isComposing: e.isComposing ?? e.nativeEvent?.isComposing,
|
|
68
|
-
// Safari's only honest IME signal on this keydown. Dropping it here would
|
|
69
|
-
// put the mid-candidate submit straight back, whatever `sends` checks.
|
|
70
|
-
keyCode: e.keyCode ?? e.nativeEvent?.keyCode,
|
|
110
|
+
function useLift() {
|
|
111
|
+
const [lift, setLift] = (0, react_2.useState)(0);
|
|
112
|
+
(0, react_2.useEffect)(() => {
|
|
113
|
+
const vv = typeof window === 'undefined' ? null : window.visualViewport;
|
|
114
|
+
if (!vv)
|
|
115
|
+
return;
|
|
116
|
+
const read = () => {
|
|
117
|
+
const covered = Math.round(window.innerHeight - vv.height - vv.offsetTop);
|
|
118
|
+
// A bar of the browser's own coming and going is not a keyboard.
|
|
119
|
+
setLift(covered > 100 ? covered : 0);
|
|
71
120
|
};
|
|
72
|
-
|
|
121
|
+
read();
|
|
122
|
+
vv.addEventListener('resize', read);
|
|
123
|
+
vv.addEventListener('scroll', read);
|
|
124
|
+
return () => {
|
|
125
|
+
vv.removeEventListener('resize', read);
|
|
126
|
+
vv.removeEventListener('scroll', read);
|
|
127
|
+
};
|
|
128
|
+
}, []);
|
|
129
|
+
return lift;
|
|
130
|
+
}
|
|
131
|
+
function Composer({ value, onChange, onSend, onStop, busy = false, disabled = false, ready: readyProp, placeholder, label, rows = 1, maxHeight = CEILING, field, hint, children, head, pills, carried, plus, slash, at, commands, chips, mind, effort, limits, onUpgrade, mode, voice, language = null, onLanguage, talk, starters, note, column = false, framed = false, narrow: narrowProp, defaults, ...props }) {
|
|
132
|
+
const { t } = (0, react_1.useI18n)();
|
|
133
|
+
const media = (0, gui_1.useMedia)();
|
|
134
|
+
const narrow = narrowProp ?? !media.sm;
|
|
135
|
+
const hit = narrow ? TAP : exports.ROUND;
|
|
136
|
+
const lift = useLift();
|
|
137
|
+
const chosen = (0, appearance_1.useComposing)();
|
|
138
|
+
const rule = chosen.send ?? defaults?.send ?? 'enter';
|
|
139
|
+
const showChips = chosen.chips ?? defaults?.chips ?? true;
|
|
140
|
+
const showModel = chosen.model ?? defaults?.model ?? false;
|
|
141
|
+
const showMode = chosen.mode ?? defaults?.mode ?? true;
|
|
142
|
+
const lit = readyProp ?? (0, send_1.ready)(value);
|
|
143
|
+
const live = busy ? Boolean(onStop) : lit && !disabled;
|
|
144
|
+
useUpload(plus?.upload);
|
|
145
|
+
// `/` and `@`: the shelf the caret's word opens, filtered by what follows it.
|
|
146
|
+
const [index, setIndex] = (0, react_2.useState)(0);
|
|
147
|
+
const [closed, setClosed] = (0, react_2.useState)(null);
|
|
148
|
+
const typed = (0, Mention_1.trigger)(value);
|
|
149
|
+
const shelf = typed ? (typed.char === '/' ? slash : at) : undefined;
|
|
150
|
+
const listed = shelf && typed && closed !== value ? shelf.rows.filter((r) => r.label.toLowerCase().includes(typed.query)).slice(0, 8) : null;
|
|
151
|
+
const row = Math.min(index, Math.max(0, (listed?.length ?? 1) - 1));
|
|
152
|
+
(0, react_2.useEffect)(() => setIndex(0), [typed?.char, typed?.query]);
|
|
153
|
+
const pick = (id) => {
|
|
154
|
+
if (!typed || !shelf)
|
|
73
155
|
return;
|
|
74
|
-
|
|
75
|
-
|
|
156
|
+
onChange(value.slice(0, typed.at).trimEnd() + (typed.at > 0 ? ' ' : ''));
|
|
157
|
+
shelf.pick(id);
|
|
158
|
+
};
|
|
159
|
+
const [palette, setPalette] = (0, react_2.useState)(false);
|
|
160
|
+
const submit = () => {
|
|
161
|
+
if (listed?.length)
|
|
162
|
+
return pick(listed[row].id);
|
|
163
|
+
if (live && !busy)
|
|
76
164
|
onSend();
|
|
77
165
|
};
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
166
|
+
const keyed = (e) => {
|
|
167
|
+
const key = e?.key ?? e?.nativeEvent?.key ?? '';
|
|
168
|
+
const mods = modsOf(e ?? {});
|
|
169
|
+
if (listed) {
|
|
170
|
+
if (key === 'ArrowDown') {
|
|
171
|
+
e.preventDefault?.();
|
|
172
|
+
return setIndex((i) => Math.min(i + 1, listed.length - 1));
|
|
173
|
+
}
|
|
174
|
+
if (key === 'ArrowUp') {
|
|
175
|
+
e.preventDefault?.();
|
|
176
|
+
return setIndex((i) => Math.max(0, i - 1));
|
|
87
177
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
178
|
+
if (key === 'Escape') {
|
|
179
|
+
e.preventDefault?.();
|
|
180
|
+
return setClosed(value);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (commands?.length && (mods.metaKey || mods.ctrlKey) && key.toLowerCase() === 'k') {
|
|
184
|
+
e.preventDefault?.();
|
|
185
|
+
return setPalette(true);
|
|
186
|
+
}
|
|
187
|
+
if (!(0, send_1.sends)(key, mods, rule))
|
|
188
|
+
return;
|
|
189
|
+
e.preventDefault?.();
|
|
190
|
+
submit();
|
|
191
|
+
};
|
|
192
|
+
const input = ((0, jsx_runtime_1.jsx)(gui_2.Textarea, { ...(0, slot_1.slot)('composer-field'), rows: rows, placeholder: placeholder ?? t(exports.ASK), disabled: disabled, borderWidth: 0, fontSize: 16, lineHeight: 24, px: 8, pt: 2, pb: 0, minH: 26, maxH: maxHeight, bg: "transparent", "aria-label": label ?? placeholder ?? t(exports.ASK), ...field,
|
|
193
|
+
// After `field`: a caller's `onKeyDown` runs first and can claim the key,
|
|
194
|
+
// but cannot replace the send rule and the IME guard.
|
|
91
195
|
value: value, onChangeText: onChange, onKeyDown: (e) => {
|
|
92
196
|
field?.onKeyDown?.(e);
|
|
93
197
|
if (!e?.defaultPrevented)
|
|
94
198
|
keyed(e);
|
|
95
199
|
} }));
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
if (e?.key !== 'Enter' && e?.key !== ' ')
|
|
99
|
-
return;
|
|
100
|
-
e.preventDefault?.();
|
|
101
|
-
if (busy)
|
|
102
|
-
onStop?.();
|
|
103
|
-
else if (sendable)
|
|
104
|
-
onSend();
|
|
105
|
-
}, children: busy ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Square, { size: 12, color: "$soft" }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.CornerDownLeft, { size: 14, color: "$soft" }) }))] })) : ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('composer'), width: "100%", rounded: "$5", borderWidth: 1, borderColor: "$borderColor", bg: "$background", p: PAD, gap: PAD, ...props, children: [input, (0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: PAD, children: [children, (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1 }), said, send ?? ((0, jsx_runtime_1.jsx)(gui_2.Button, { ...(0, slot_1.slot)('composer-send'), size: "sm", disabled: busy ? !onStop : !sendable, onPress: busy ? onStop : onSend, "aria-label": busy ? 'Stop' : 'Send',
|
|
106
|
-
// A circle, and the room's one primary control. The height is the
|
|
107
|
-
// size's; `aspectRatio` takes the width from it, so no second number
|
|
108
|
-
// is written down. `--primary` is the accent a reader picks, and at
|
|
109
|
-
// rest it is the ink pair Send already paints in both themes.
|
|
110
|
-
px: 0, aspectRatio: 1, rounded: 'var(--radius-full, 9999px)', bg: "var(--primary)", borderWidth: 0, hoverStyle: { bg: 'var(--primary)', opacity: 0.9 }, pressStyle: { bg: 'var(--primary)', opacity: 0.85 }, children: busy ? ((0, jsx_runtime_1.jsx)(lucide_icons_2_1.Square, { size: 14, color: 'var(--primary-foreground)' })) : ((0, jsx_runtime_1.jsx)(lucide_icons_2_1.ArrowUp, { size: 16, color: 'var(--primary-foreground)' })) }))] })] }));
|
|
111
|
-
// With nothing above or below it the composer IS the frame, exactly as it
|
|
112
|
-
// was before either existed — no wrapper, so every caller's tree is unchanged.
|
|
113
|
-
if (!head && !foot)
|
|
114
|
-
return frame;
|
|
115
|
-
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('composer-shell'), width: "100%", gap: "$2.5", children: [head ? ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('composer-head'), items: "center", gap: "$1.5", flexWrap: "wrap", children: head })) : null, frame, foot ? ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('composer-foot'), items: "center", gap: "$2", px: "$1.5", mt: -4, children: foot })) : null] }));
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* ComposerTool — one quiet control in a composer's `foot` or `head`: attach,
|
|
119
|
-
* voice, a mode, the model. 24px tall, muted until pointed at, and a real
|
|
120
|
-
* button to the keyboard. Its name is `label` whether or not it shows words,
|
|
121
|
-
* because an icon-only control is the whole navigation for someone who cannot
|
|
122
|
-
* see the icon.
|
|
123
|
-
*/
|
|
124
|
-
function ComposerTool({ label, icon, text, caret = false, onPress, disabled = false, ...rest }) {
|
|
125
|
-
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('composer-tool'), ...(0, slot_1.tip)(label), role: "button", tabIndex: disabled ? -1 : 0, "aria-label": label, "aria-disabled": disabled || undefined, "aria-haspopup": caret ? 'menu' : undefined, height: 24, px: text ? '$1.5' : '$1', gap: "$1", items: "center", rounded: "$2", shrink: 0, cursor: disabled ? 'default' : 'pointer', opacity: disabled ? 0.5 : 1, hoverStyle: disabled ? undefined : { bg: '$hover' }, focusVisibleStyle: { outlineColor: '$outlineColor', outlineWidth: 2, outlineStyle: 'solid' }, hitSlop: { top: 10, bottom: 10, left: 2, right: 2 }, onPress: disabled ? undefined : onPress, onKeyDown: (e) => {
|
|
126
|
-
if (disabled || (e?.key !== 'Enter' && e?.key !== ' '))
|
|
200
|
+
const round = ((0, jsx_runtime_1.jsx)(composer_1.Control, { type: "button", size: hit, fill: true, rounded: 999, ...(0, slot_1.slot)('composer-send'), "aria-label": t(busy ? 'Stop' : 'Send'), "aria-disabled": !live || undefined, opacity: live ? 1 : 0.4, focusVisibleStyle: ring_1.RING, onClick: () => {
|
|
201
|
+
if (!live)
|
|
127
202
|
return;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
203
|
+
if (busy)
|
|
204
|
+
onStop?.();
|
|
205
|
+
else
|
|
206
|
+
onSend();
|
|
207
|
+
}, children: busy ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Square, { size: 13, color: ON, fill: ON }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ArrowUp, { size: 16, strokeWidth: 2.5, color: ON }) }));
|
|
208
|
+
const mention = listed && shelf && typed ? (0, jsx_runtime_1.jsx)(Mention_1.Mention, { shelf: shelf, rows: listed, index: row, onPick: pick, skills: typed.char === '/' }) : null;
|
|
209
|
+
const above = starters || head || note || mention ? ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('composer-head'), gap: "$1.5", children: [starters, head, mention, note ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { ...(0, slot_1.slot)('composer-note'), fontSize: 12, color: "$soft", text: "center", self: "center", children: note })) : null] })) : null;
|
|
210
|
+
const shown = showChips && chips?.length ? chips : null;
|
|
211
|
+
const tuned = (showModel && mind) || (showMode && mode);
|
|
212
|
+
const under = shown || tuned ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('composer-foot'), items: "center", gap: 6, flexWrap: "wrap", rowGap: 4, width: "100%", children: [shown ? (0, jsx_runtime_1.jsx)(Tune_1.Chips, { chips: shown }) : null, tuned ? (0, jsx_runtime_1.jsx)(Tune_1.Tune, { mind: showModel ? mind : null, mode: showMode ? mode : null, onUpgrade: onUpgrade, limits: limits }) : null] })) : null;
|
|
213
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('composer-shell'), ...(column ? exports.measure : { width: '100%' }), gap: 6, ...(lift ? { mb: lift } : null), ...props, children: [above, (0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('composer'), width: "100%", rounded: CORNER, borderWidth: 1, ...(0, glass_1.glass)(2), p: 6, pt: pills ? 6 : 10, gap: 4, "$max-sm": { rounded: CORNER_PHONE }, ...(framed ? { boxShadow: 'var(--shadow-sheet-1)' } : null), children: [pills ? ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('composer-pills'), items: "center", gap: 4, flexWrap: "wrap", rowGap: 4, px: 2, children: pills })) : null, input, (0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: 4, children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('composer-start'), items: "center", gap: 4, flex: 1, minW: 0, flexWrap: "wrap", children: [plus ? (0, jsx_runtime_1.jsx)(Plus_1.Plus, { ...plus, size: hit, disabled: disabled || plus.disabled }) : null, (carried ?? []).map((c) => ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('composer-carried'), items: "center", gap: 6, paddingInlineStart: 8, paddingInlineEnd: 4, height: 28, rounded: 8, bg: "$hover", maxW: 180, children: [c.icon ? (0, jsx_runtime_1.jsx)(gui_1.XStack, { "aria-hidden": true, children: c.icon }) : null, (0, jsx_runtime_1.jsx)(gui_1.SizableText, { fontSize: 13, color: "$ink", numberOfLines: 1, shrink: 1, children: c.label }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { render: "button", "aria-label": t('Remove {name}', { name: c.label }), onPress: c.onRemove, width: 20, height: 20, rounded: 6, items: "center", justify: "center", hoverStyle: { bg: '$raised' }, cursor: "pointer", children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.X, { size: 12, color: "$hint" }) })] }, c.id))), children] }), (0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...(0, slot_1.slot)('composer-end'), items: "center", gap: 4, shrink: 0, children: [hint ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: "$soft", numberOfLines: 1, children: hint })) : null, effort ? (0, jsx_runtime_1.jsx)(Dial_1.Dial, { effort: effort, size: hit, disabled: disabled }) : null, commands?.length ? (0, jsx_runtime_1.jsx)(Palette_1.Palette, { commands: commands, open: palette, onOpenChange: setPalette, size: hit, disabled: disabled }) : null, voice ? (0, jsx_runtime_1.jsx)(Dictation_1.Dictation, { voice: voice, disabled: disabled, size: hit, language: language, ...(onLanguage ? { onLanguage } : {}) }) : null, !busy && !lit && talk ? ((0, jsx_runtime_1.jsx)(composer_1.Control, { asChild: true, size: hit, fill: narrow, rounded: 999, ...(narrow ? null : QUIET), focusVisibleStyle: ring_1.RING, children: (0, jsx_runtime_1.jsx)(voice_1.Voice, { voice: talk, disabled: disabled, "data-slot": "composer-talk", says: { idle: t('Voice mode'), listening: t('In conversation — click to hang up'), speaking: t('Hanzo is speaking — talk to interrupt') }, children: () => (0, jsx_runtime_1.jsx)(lucide_icons_2_1.AudioLines, { size: 16, color: narrow ? ON : 'var(--foreground)' }) }) })) : (round)] })] })] }), under] }));
|
|
131
214
|
}
|
package/dist/chat/Composer.d.ts
CHANGED
|
@@ -1,109 +1,138 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Composer — the one
|
|
2
|
+
* Composer — the one composer every Hanzo surface draws: Chat, Dev, Studio, a
|
|
3
|
+
* room, a reply, a run being steered. A surface hands it slots and defaults and
|
|
4
|
+
* nothing else; the field, the keys, the controls and their look are here once.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* ┌ pills ───────────────────────────────┐ where a run goes, which repository
|
|
7
|
+
* │ the field │
|
|
8
|
+
* │ + carried… children ✦ 🎙 ⬆ │ + menu, what the draft carries,
|
|
9
|
+
* └──────────────────────────────────────┘ commands, dictation, send / stop
|
|
10
|
+
* chips… model effort mode
|
|
8
11
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* surface got subtly different.
|
|
12
|
+
* Above the frame: the surface's `head`, the `/` or `@` list, and the `note`.
|
|
13
|
+
* Under it, one row: the surface's chips, then the model, the effort and the mode.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
+
* THE PERSON'S SETTING (@hanzo/appearance `useComposing`, Settings →
|
|
16
|
+
* Appearance) decides which key sends and whether the chips, the model
|
|
17
|
+
* selector and the mode are drawn, everywhere at once. An axis they left on
|
|
18
|
+
* Auto takes the surface's `defaults`, and the model selector is off until
|
|
19
|
+
* they turn it on.
|
|
15
20
|
*
|
|
16
|
-
*
|
|
17
|
-
* the
|
|
21
|
+
* Its paint is @hanzo/design's: `$` tokens and `--primary`, sized through
|
|
22
|
+
* `--density` (the round controls are @hanzo/composer's `Control`), so text
|
|
23
|
+
* size, density and accent change it with the rest of the product.
|
|
24
|
+
*
|
|
25
|
+
* Its own words are the reader's language (@hanzo/i18n `t`). A host's words —
|
|
26
|
+
* its placeholder, a shelf's rows, a chip's label — are drawn as given.
|
|
18
27
|
*/
|
|
19
|
-
import {
|
|
20
|
-
import
|
|
28
|
+
import { YStack } from '@hanzo/gui';
|
|
29
|
+
import { type Composing } from '@hanzo/appearance';
|
|
30
|
+
import { type Machine } from '@hanzo/voice';
|
|
31
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
21
32
|
import { Textarea } from '../backends/gui/index.js';
|
|
33
|
+
import type { PauseSource } from '../models/catalog.js';
|
|
34
|
+
import { type Command } from './Palette.js';
|
|
35
|
+
import { type PlusProps, type Shelf } from './Plus.js';
|
|
36
|
+
import { type Chip, type Mind, type Modes } from './Tune.js';
|
|
22
37
|
/** `onChange` is dropped: here it carries the draft, not a DOM change event. */
|
|
23
38
|
type Stack = Omit<ComponentProps<typeof YStack>, 'children' | 'onChange'>;
|
|
24
39
|
type FieldProps = Omit<ComponentProps<typeof Textarea>, 'value' | 'onChangeText'>;
|
|
25
40
|
/**
|
|
26
|
-
* The resting placeholder.
|
|
27
|
-
*
|
|
28
|
-
* "Ask anything", not "Send a message" and not "Message <model>". It addresses
|
|
29
|
-
* the person rather than describing the mechanism, and being one constant string
|
|
30
|
-
* it never has to be recomputed or re-announced when the model or endpoint
|
|
31
|
-
* changes — which is what a model-named placeholder forces a surface to do.
|
|
41
|
+
* The resting placeholder. It addresses the person rather than the mechanism,
|
|
42
|
+
* and as one constant it never re-announces when the model changes.
|
|
32
43
|
*/
|
|
33
|
-
export declare const ASK
|
|
44
|
+
export declare const ASK: string;
|
|
45
|
+
/** The reading measure: @hanzo/design's prose width, which Width (appearance) retunes. */
|
|
46
|
+
export declare const MEASURE = "var(--container-prose, 48rem)";
|
|
47
|
+
/** The space between turns, px: one rhythm for every thread. */
|
|
48
|
+
export declare const GAP = 20;
|
|
49
|
+
/** The composer's width under a thread: the measure less its 0.75rem gutters, centred, so its edges are the text's. */
|
|
50
|
+
export declare const measure: {
|
|
51
|
+
readonly width: 'calc(100% - 1.5rem)';
|
|
52
|
+
readonly maxW: "calc(var(--container-prose, 48rem) - 1.5rem)";
|
|
53
|
+
readonly mx: 'auto';
|
|
54
|
+
};
|
|
55
|
+
/** The round controls' box, px, and a phone's, a thumb's width kept small so the frame is a slim glass bar: `+`, the effort, the mic, its chevron and send all take it, so they share one centreline. */
|
|
56
|
+
export declare const ROUND = 32;
|
|
57
|
+
/** One thing the draft carries, after `+`: a file, a skill that is on. */
|
|
58
|
+
export interface Carried {
|
|
59
|
+
id: string;
|
|
60
|
+
label: string;
|
|
61
|
+
icon?: ReactNode;
|
|
62
|
+
onRemove: () => void;
|
|
63
|
+
}
|
|
34
64
|
export interface ComposerProps extends Stack {
|
|
35
65
|
value: string;
|
|
36
66
|
onChange: (value: string) => void;
|
|
37
|
-
/**
|
|
67
|
+
/** The draft is submitted. Clearing `value` is the host's job. */
|
|
38
68
|
onSend: () => void;
|
|
39
|
-
/** Called instead of `onSend` while `busy`.
|
|
69
|
+
/** Called instead of `onSend` while `busy`. Absent, busy only disables send. */
|
|
40
70
|
onStop?: () => void;
|
|
41
|
-
/** A turn is in flight:
|
|
71
|
+
/** A turn is in flight: send becomes stop. */
|
|
42
72
|
busy?: boolean;
|
|
43
73
|
disabled?: boolean;
|
|
74
|
+
/** Whether send is lit. Default: the draft has words. */
|
|
75
|
+
ready?: boolean;
|
|
44
76
|
placeholder?: string;
|
|
77
|
+
/** The field's accessible name, independent of the placeholder. */
|
|
78
|
+
label?: string;
|
|
45
79
|
/** Row floor for the field. It grows with the draft from here. */
|
|
46
80
|
rows?: number;
|
|
47
|
-
/** Ceiling for that growth, px. Past it the field scrolls
|
|
81
|
+
/** Ceiling for that growth, px. Past it the field scrolls. */
|
|
48
82
|
maxHeight?: number;
|
|
49
|
-
/**
|
|
50
|
-
children?: ReactNode;
|
|
51
|
-
/** Hint shown at the end of the footer row. */
|
|
52
|
-
hint?: string;
|
|
53
|
-
/**
|
|
54
|
-
* The accessible name of the field, independent of `placeholder`.
|
|
55
|
-
*
|
|
56
|
-
* A placeholder that rotates renames the control on every tick and gets the
|
|
57
|
-
* field re-announced mid-sentence. The name is stable; the placeholder is
|
|
58
|
-
* decoration.
|
|
59
|
-
*/
|
|
60
|
-
label?: string;
|
|
61
|
-
/** The field's own props — a ref, a testid, focus handlers, a paste handler. */
|
|
83
|
+
/** The field's own props — a ref, a testid, a paste handler. */
|
|
62
84
|
field?: FieldProps;
|
|
63
|
-
/**
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* runs, which repository, which branch). Outside the frame on purpose: it
|
|
69
|
-
* says what the draft is about, and the field says what it is.
|
|
70
|
-
*/
|
|
85
|
+
/** A word at the end of the tool row, before the controls: a status. */
|
|
86
|
+
hint?: string;
|
|
87
|
+
/** The tool row's start, after `+` and what the draft carries. */
|
|
88
|
+
children?: ReactNode;
|
|
89
|
+
/** Above the frame, at its width: what the draft is sent with, a banner. */
|
|
71
90
|
head?: ReactNode;
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
/** The frame's first row: the surface's pills — where a run goes, which repository, which branch. */
|
|
92
|
+
pills?: ReactNode;
|
|
93
|
+
/** What the draft carries, as chips after `+`. */
|
|
94
|
+
carried?: readonly Carried[];
|
|
95
|
+
/** The `+` menu. Absent, there is none. */
|
|
96
|
+
plus?: PlusProps;
|
|
97
|
+
/** `/` lists these (the skills) above the frame. */
|
|
98
|
+
slash?: Shelf;
|
|
99
|
+
/** `@` lists these (the plugins) above the frame. */
|
|
100
|
+
at?: Shelf;
|
|
101
|
+
/** The commands ✦ and ⌘K open. */
|
|
102
|
+
commands?: readonly Command[];
|
|
103
|
+
/** Under the frame, at the row's start. Hidden where the person hid chips. */
|
|
104
|
+
chips?: readonly Chip[];
|
|
105
|
+
/** The model, drawn where the person turned the model selector on. Null where the next send names none (steering a run). */
|
|
106
|
+
mind?: Mind | null;
|
|
107
|
+
/** The effort, one in force. Null where the next send takes none (steering a run). */
|
|
108
|
+
effort?: Modes | null;
|
|
109
|
+
limits?: PauseSource | null;
|
|
110
|
+
/** A model the plan does not grant was chosen: the way to the plan that does. */
|
|
111
|
+
onUpgrade?: (model: string) => void;
|
|
112
|
+
/** The mode, as the pill at the row's end. */
|
|
113
|
+
mode?: Modes | null;
|
|
114
|
+
/** Dictation into the draft (@hanzo/voice `useVoice` + `useDictation`). */
|
|
115
|
+
voice?: Machine;
|
|
116
|
+
/** The language dictation listens in, null for Auto, and how to change it. */
|
|
117
|
+
language?: string | null;
|
|
118
|
+
onLanguage?: (id: string | null) => void;
|
|
119
|
+
/** A spoken conversation (@hanzo/voice `useTalk`): the round button while the draft is empty. */
|
|
120
|
+
talk?: Machine;
|
|
121
|
+
/** Above the frame, nearest it: the person's suggestions, at every width. */
|
|
122
|
+
starters?: ReactNode;
|
|
123
|
+
/** Centred just above the frame: what every message is sent under. */
|
|
124
|
+
note?: ReactNode;
|
|
125
|
+
/** At the reading column's width (`measure`), centred: the composer under a thread, so its edges are the text's. Absent, the width of what holds it. */
|
|
126
|
+
column?: boolean;
|
|
127
|
+
/** Drawn on a pane: the frame floats as a pane of its own. */
|
|
128
|
+
framed?: boolean;
|
|
129
|
+
/** A phone: suggestions go above the frame and every target is 44px. Absent, the viewport decides. */
|
|
130
|
+
narrow?: boolean;
|
|
131
|
+
/** This surface's answer where the person left an axis on Auto. */
|
|
132
|
+
defaults?: Composing;
|
|
99
133
|
}
|
|
100
|
-
/**
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* button to the keyboard. Its name is `label` whether or not it shows words,
|
|
104
|
-
* because an icon-only control is the whole navigation for someone who cannot
|
|
105
|
-
* see the icon.
|
|
106
|
-
*/
|
|
107
|
-
export declare function ComposerTool({ label, icon, text, caret, onPress, disabled, ...rest }: ComposerToolProps): import("react").JSX.Element;
|
|
134
|
+
/** Ctrl+U (⌘U) uploads, while a composer with an upload is on the page. */
|
|
135
|
+
export declare function useUpload(upload: (() => void) | undefined): void;
|
|
136
|
+
export declare function Composer({ value, onChange, onSend, onStop, busy, disabled, ready: readyProp, placeholder, label, rows, maxHeight, field, hint, children, head, pills, carried, plus, slash, at, commands, chips, mind, effort, limits, onUpgrade, mode, voice, language, onLanguage, talk, starters, note, column, framed, narrow: narrowProp, defaults, ...props }: ComposerProps): import("react").JSX.Element;
|
|
108
137
|
export {};
|
|
109
138
|
//# sourceMappingURL=Composer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Composer.d.ts","sourceRoot":"","sources":["../../src/chat/Composer.tsx"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"Composer.d.ts","sourceRoot":"","sources":["../../src/chat/Composer.tsx"],"names":[],"mappings":"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"}
|