@hanzo/ui 8.1.5 → 8.1.6
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/backends/gui/textarea.cjs +5 -10
- package/dist/backends/gui/textarea.d.ts +11 -32
- package/dist/backends/gui/textarea.d.ts.map +1 -1
- package/dist/backends/gui/textarea.js +5 -10
- package/dist/backends/gui/textarea.js.map +1 -1
- package/dist/chat/Composer.cjs +10 -46
- package/dist/chat/Composer.d.ts +11 -30
- package/dist/chat/Composer.d.ts.map +1 -1
- package/dist/chat/Composer.js +10 -46
- package/dist/chat/Composer.js.map +1 -1
- package/dist/chat/Failure.cjs +9 -28
- package/dist/chat/Failure.d.ts +6 -20
- package/dist/chat/Failure.d.ts.map +1 -1
- package/dist/chat/Failure.js +9 -28
- package/dist/chat/Failure.js.map +1 -1
- package/dist/chat/Message.cjs +11 -34
- package/dist/chat/Message.d.ts +12 -40
- package/dist/chat/Message.d.ts.map +1 -1
- package/dist/chat/Message.js +11 -34
- package/dist/chat/Message.js.map +1 -1
- package/dist/chat/Sources.cjs +6 -24
- package/dist/chat/Sources.d.ts +8 -28
- package/dist/chat/Sources.d.ts.map +1 -1
- package/dist/chat/Sources.js +6 -24
- package/dist/chat/Sources.js.map +1 -1
- package/dist/chat/Step.cjs +16 -42
- package/dist/chat/Step.d.ts +5 -17
- package/dist/chat/Step.d.ts.map +1 -1
- package/dist/chat/Step.js +16 -42
- package/dist/chat/Step.js.map +1 -1
- package/dist/chat/Thread.cjs +4 -27
- package/dist/chat/Thread.d.ts +4 -34
- package/dist/chat/Thread.d.ts.map +1 -1
- package/dist/chat/Thread.js +4 -27
- package/dist/chat/Thread.js.map +1 -1
- package/dist/chat/index.cjs +20 -61
- package/dist/chat/index.d.ts +20 -61
- package/dist/chat/index.d.ts.map +1 -1
- package/dist/chat/index.js +20 -61
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/pure.cjs +9 -28
- package/dist/chat/pure.d.ts.map +1 -1
- package/dist/chat/pure.js +9 -28
- package/dist/chat/pure.js.map +1 -1
- package/dist/chat/send.cjs +8 -18
- package/dist/chat/send.d.ts +5 -12
- package/dist/chat/send.d.ts.map +1 -1
- package/dist/chat/send.js +8 -18
- package/dist/chat/send.js.map +1 -1
- package/dist/chat/stick.cjs +2 -4
- package/dist/chat/stick.d.ts +2 -4
- package/dist/chat/stick.d.ts.map +1 -1
- package/dist/chat/stick.js +2 -4
- package/dist/chat/stick.js.map +1 -1
- package/dist/gallery.d.ts.map +1 -1
- package/dist/gallery.js.map +1 -1
- package/dist/product/CopyButton.d.ts +2 -8
- package/dist/product/CopyButton.d.ts.map +1 -1
- package/dist/product/CopyButton.js.map +1 -1
- package/dist/product/pure.cjs +3 -5
- package/dist/product/pure.d.ts.map +1 -1
- package/dist/product/pure.js +3 -5
- package/dist/product/pure.js.map +1 -1
- package/package.json +1 -1
|
@@ -49,9 +49,7 @@ const Textarea = /* @__PURE__ */ React.forwardRef(function Textarea({ rows, valu
|
|
|
49
49
|
const invalid = props["aria-invalid"];
|
|
50
50
|
const node = React.useRef(null);
|
|
51
51
|
const [grown, setGrown] = React.useState(undefined);
|
|
52
|
-
// Both refs reach the same host: ours to measure it, the caller's
|
|
53
|
-
// caller that hands one over must still get it. Written as a callback so
|
|
54
|
-
// neither is dropped on the other's behalf.
|
|
52
|
+
// Both refs reach the same host: ours to measure it, and the caller's.
|
|
55
53
|
const hold = React.useCallback((el) => {
|
|
56
54
|
node.current = el;
|
|
57
55
|
if (typeof ref === "function")
|
|
@@ -59,16 +57,14 @@ const Textarea = /* @__PURE__ */ React.forwardRef(function Textarea({ rows, valu
|
|
|
59
57
|
else if (ref)
|
|
60
58
|
ref.current = el;
|
|
61
59
|
}, [ref]);
|
|
62
|
-
//
|
|
63
|
-
// uncontrolled one has to be watched, and both have to re-measure.
|
|
60
|
+
// What the field is showing: told when controlled, watched when not.
|
|
64
61
|
const shown = uncontrolled ? typed : value;
|
|
65
62
|
React.useLayoutEffect(() => {
|
|
66
63
|
const el = node.current;
|
|
67
64
|
if (!el || typeof el.scrollHeight !== "number")
|
|
68
65
|
return;
|
|
69
66
|
// Released to `auto` first, or `scrollHeight` reports the height it already
|
|
70
|
-
// has and the field can only
|
|
71
|
-
// block, before paint, so nothing flashes.
|
|
67
|
+
// has and the field can only grow. Restored before paint.
|
|
72
68
|
const held = el.style.height;
|
|
73
69
|
el.style.height = "auto";
|
|
74
70
|
const measured = el.scrollHeight;
|
|
@@ -81,9 +77,8 @@ const Textarea = /* @__PURE__ */ React.forwardRef(function Textarea({ rows, valu
|
|
|
81
77
|
// landed on 20 — so the one field a form makes tall was also the one
|
|
82
78
|
// indented differently from the two above it.
|
|
83
79
|
borderColor: invalid && invalid !== "false" ? "$red7" : "$borderColor", placeholderTextColor: "$color10", fontSize: "$3", opacity: props.disabled ? 0.5 : 1, ...props,
|
|
84
|
-
// After the caller's props
|
|
85
|
-
//
|
|
86
|
-
// growth off. A caller wanting a fixed height says so with `height`.
|
|
80
|
+
// After the caller's props, so a passed `style` cannot silently disable
|
|
81
|
+
// growth. A fixed height is asked for with `height`.
|
|
87
82
|
style: { ...style, ...(grown ? { height: grown } : null) } }));
|
|
88
83
|
});
|
|
89
84
|
exports.Textarea = Textarea;
|
|
@@ -1,41 +1,20 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { TextArea } from "@hanzo/gui";
|
|
3
3
|
/**
|
|
4
|
-
* Textarea — standard-token multiline field that grows with
|
|
4
|
+
* Textarea — standard-token multiline field that grows with its content.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* Measured in Chromium at 420px wide: 700 characters and no `\n` gave
|
|
12
|
-
* `clientHeight 44` around `scrollHeight 160`.
|
|
6
|
+
* The height is measured off the node and applied INLINE. Two nearer-looking
|
|
7
|
+
* routes do not work here: `onContentSizeChange` never fires, because gui's
|
|
8
|
+
* `TextArea` is `styled(Input, { render: 'textarea' })` over a real DOM element
|
|
9
|
+
* rather than react-native-web's `TextInput`; and a `height` style prop would
|
|
10
|
+
* mint one atomic class per pixel value, none of them in the packaged sheet.
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* `rows` is the floor and `maxH` the ceiling — CSS clamps between them and the
|
|
13
|
+
* field scrolls past the ceiling, so neither bound is re-implemented here.
|
|
14
|
+
* Counting newlines instead would miss a paragraph that wraps without one.
|
|
16
15
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* (`dist/exports/TextInput/index.js:192`). It never fires through this
|
|
20
|
-
* component — measured, zero calls, no warning. gui's `TextArea` is
|
|
21
|
-
* `styled(Input, { render: 'textarea' })` from `@hanzogui/web`: a Tamagui
|
|
22
|
-
* styled component over a real DOM `<textarea>`, so RNW's `TextInput` is not
|
|
23
|
-
* on the path and neither is its implementation of that prop.
|
|
24
|
-
*
|
|
25
|
-
* A `height` STYLE PROP would be compiled by gui into one atomic class per
|
|
26
|
-
* distinct pixel value, so a field that grows through forty heights mints
|
|
27
|
-
* forty rules at runtime — none of them in the packaged sheet.
|
|
28
|
-
*
|
|
29
|
-
* So the height is measured off the node and applied INLINE, which is the one
|
|
30
|
-
* channel that carries a per-render value without going through the atomic
|
|
31
|
-
* compiler. `rows` stays the floor and `maxH` stays the ceiling; CSS clamps
|
|
32
|
-
* between them and the field scrolls past the ceiling, so neither bound is
|
|
33
|
-
* re-implemented in script.
|
|
34
|
-
*
|
|
35
|
-
* The measurement is guarded on `scrollHeight` actually being a number, so on a
|
|
36
|
-
* target where the host is not a DOM element the effect no-ops and the
|
|
37
|
-
* line-driven floor is what remains — today's behaviour, unchanged, rather than
|
|
38
|
-
* a broken one.
|
|
16
|
+
* Guarded on `scrollHeight` being a number, so where the host is not a DOM
|
|
17
|
+
* element the effect no-ops and the row count is what remains.
|
|
39
18
|
*/
|
|
40
19
|
/**
|
|
41
20
|
* Typed from the gui component it renders, exactly as `Input` is — the field
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/textarea.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAUrC
|
|
1
|
+
{"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/textarea.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAUrC;;;;;;;;;;;;;;;GAeG;AACH;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,EAAE,UAAU,CAAC,GACjF,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,CAAA;AAE9D,QAAA,MAAM,QAAQ,wGA4Db,CAAA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -13,9 +13,7 @@ const Textarea = /* @__PURE__ */ React.forwardRef(function Textarea({ rows, valu
|
|
|
13
13
|
const invalid = props["aria-invalid"];
|
|
14
14
|
const node = React.useRef(null);
|
|
15
15
|
const [grown, setGrown] = React.useState(undefined);
|
|
16
|
-
// Both refs reach the same host: ours to measure it, the caller's
|
|
17
|
-
// caller that hands one over must still get it. Written as a callback so
|
|
18
|
-
// neither is dropped on the other's behalf.
|
|
16
|
+
// Both refs reach the same host: ours to measure it, and the caller's.
|
|
19
17
|
const hold = React.useCallback((el) => {
|
|
20
18
|
node.current = el;
|
|
21
19
|
if (typeof ref === "function")
|
|
@@ -23,16 +21,14 @@ const Textarea = /* @__PURE__ */ React.forwardRef(function Textarea({ rows, valu
|
|
|
23
21
|
else if (ref)
|
|
24
22
|
ref.current = el;
|
|
25
23
|
}, [ref]);
|
|
26
|
-
//
|
|
27
|
-
// uncontrolled one has to be watched, and both have to re-measure.
|
|
24
|
+
// What the field is showing: told when controlled, watched when not.
|
|
28
25
|
const shown = uncontrolled ? typed : value;
|
|
29
26
|
React.useLayoutEffect(() => {
|
|
30
27
|
const el = node.current;
|
|
31
28
|
if (!el || typeof el.scrollHeight !== "number")
|
|
32
29
|
return;
|
|
33
30
|
// Released to `auto` first, or `scrollHeight` reports the height it already
|
|
34
|
-
// has and the field can only
|
|
35
|
-
// block, before paint, so nothing flashes.
|
|
31
|
+
// has and the field can only grow. Restored before paint.
|
|
36
32
|
const held = el.style.height;
|
|
37
33
|
el.style.height = "auto";
|
|
38
34
|
const measured = el.scrollHeight;
|
|
@@ -45,9 +41,8 @@ const Textarea = /* @__PURE__ */ React.forwardRef(function Textarea({ rows, valu
|
|
|
45
41
|
// landed on 20 — so the one field a form makes tall was also the one
|
|
46
42
|
// indented differently from the two above it.
|
|
47
43
|
borderColor: invalid && invalid !== "false" ? "$red7" : "$borderColor", placeholderTextColor: "$color10", fontSize: "$3", opacity: props.disabled ? 0.5 : 1, ...props,
|
|
48
|
-
// After the caller's props
|
|
49
|
-
//
|
|
50
|
-
// growth off. A caller wanting a fixed height says so with `height`.
|
|
44
|
+
// After the caller's props, so a passed `style` cannot silently disable
|
|
45
|
+
// growth. A fixed height is asked for with `height`.
|
|
51
46
|
style: { ...style, ...(grown ? { height: grown } : null) } }));
|
|
52
47
|
});
|
|
53
48
|
export { Textarea };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea.js","sourceRoot":"","sources":["../../../src/backends/gui/textarea.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,qCAAqC;AACrC,MAAM,QAAQ,GAAG,CAAC,CAAA;AAElB,MAAM,MAAM,GAAG,CAAC,CAAU,EAAE,EAAE,CAC5B,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"textarea.js","sourceRoot":"","sources":["../../../src/backends/gui/textarea.tsx"],"names":[],"mappings":"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"}
|
package/dist/chat/Composer.cjs
CHANGED
|
@@ -16,21 +16,11 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
16
16
|
* turn is in flight it stops. Two buttons in one place was the thing every
|
|
17
17
|
* surface got subtly different.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* two SUB-composers, where it dismisses the thing they float over
|
|
22
|
-
* (`SelectionAsk.tsx:85`, `EditMessage.tsx:124`), which is the host's concern
|
|
23
|
-
* and not the field's. ARROWUP recalls the last turn in exactly one composer,
|
|
24
|
-
* chat's (`useHandleKeyUp.ts:117`), and it does it by finding
|
|
25
|
-
* `document.getElementById('edit-' + parentMessageId)` and clicking it — it is
|
|
26
|
-
* a binding to their edit-in-place, not a general history recall, and there is
|
|
27
|
-
* nothing here for it to reach. Adding either would be inventing an interaction
|
|
28
|
-
* and then asking three surfaces to adopt it.
|
|
19
|
+
* Escape and ArrowUp are not bound. Dismissal belongs to whatever the composer
|
|
20
|
+
* floats inside, and history recall needs a turn store this has no view of.
|
|
29
21
|
*
|
|
30
|
-
* Growth is `Textarea`'s
|
|
31
|
-
*
|
|
32
|
-
* raises the field instead of scrolling inside it. `rows` is the floor and
|
|
33
|
-
* `maxHeight` the ceiling; both are bounds, and neither is re-implemented here.
|
|
22
|
+
* Growth is `Textarea`'s and follows the content, so a wrapped paragraph raises
|
|
23
|
+
* the field. `rows` is the floor, `maxHeight` the ceiling.
|
|
34
24
|
*/
|
|
35
25
|
const gui_1 = require("@hanzo/gui");
|
|
36
26
|
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
@@ -39,34 +29,11 @@ const slot_1 = require("../backends/gui/slot.cjs");
|
|
|
39
29
|
const send_1 = require("./send.cjs");
|
|
40
30
|
const PAD = 8;
|
|
41
31
|
const MIN_ROWS = 1;
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* 200 is the number three independent composers reached — hanzo.app `/chat`
|
|
46
|
-
* (`page.tsx:184`, `Math.min(el.scrollHeight, 200)`), hanzo/chat's
|
|
47
|
-
* `AnswerComposer.tsx:134`, and the extension's `answer/Composer.tsx:81`
|
|
48
|
-
* (`maxH={200}`). The two that differ are both fitting a NARROWER frame — the
|
|
49
|
-
* extension's in-page overlay caps at 110 (`content-script.ts:1340`) and its
|
|
50
|
-
* sidebar at 120 — and the one that differs upward, chat's main composer at
|
|
51
|
-
* `max-h-[45vh]`, is the full-page surface. So 200 is the default and the
|
|
52
|
-
* ceiling is a prop.
|
|
53
|
-
*
|
|
54
|
-
* Uncapped is not an option: the field would grow with the draft until a long
|
|
55
|
-
* paste owned the viewport and pushed the thread it belongs to off screen.
|
|
56
|
-
* Nothing capped it here before.
|
|
57
|
-
*/
|
|
32
|
+
/** How tall the field may grow before it scrolls, px. Uncapped, a long paste
|
|
33
|
+
* pushes the thread off screen; narrower frames pass their own. */
|
|
58
34
|
const CEILING = 200;
|
|
59
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* `Textarea` is a form control and stands 64px tall by default, which is right
|
|
63
|
-
* for a message body in a form and wrong for a composer: it is three lines of
|
|
64
|
-
* chrome before anything is typed. Every surface sets its own — 44 in chat
|
|
65
|
-
* (`ChatForm.tsx:334`) and in the app builder (`COMPOSER_MIN_H`), 48 in the app
|
|
66
|
-
* `/chat`. 44 is both the mode and this package's touch-target floor, so the
|
|
67
|
-
* one-line composer is exactly as tall as the smallest thing you are allowed to
|
|
68
|
-
* tap.
|
|
69
|
-
*/
|
|
35
|
+
/** Floor for the field, px. `Textarea` defaults to 64, which is three lines of
|
|
36
|
+
* chrome before anything is typed. 44 is the touch-target floor. */
|
|
70
37
|
const FLOOR = 44;
|
|
71
38
|
/**
|
|
72
39
|
* The resting placeholder.
|
|
@@ -98,11 +65,8 @@ function Composer({ value, onChange, onSend, onStop, busy = false, disabled = fa
|
|
|
98
65
|
onSend();
|
|
99
66
|
};
|
|
100
67
|
return ((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: [(0, jsx_runtime_1.jsx)(gui_2.Textarea, { ...(0, slot_1.slot)('composer-field'), rows: rows, placeholder: placeholder, disabled: disabled, borderWidth: 0, minH: FLOOR, maxH: maxHeight, "aria-label": label ?? placeholder, ...field,
|
|
101
|
-
// After `field
|
|
102
|
-
//
|
|
103
|
-
// rule and the IME guard with it, type-check, and go on looking
|
|
104
|
-
// correct until a Japanese writer typed into it. So the caller's runs
|
|
105
|
-
// FIRST and this one defers to it if it claimed the key.
|
|
68
|
+
// After `field`: spread over, a caller's `onKeyDown` would replace the
|
|
69
|
+
// Enter rule and the IME guard. Theirs runs first and can claim the key.
|
|
106
70
|
value: value, onChangeText: onChange, onKeyDown: (e) => {
|
|
107
71
|
field?.onKeyDown?.(e);
|
|
108
72
|
if (!e?.defaultPrevented)
|
package/dist/chat/Composer.d.ts
CHANGED
|
@@ -10,27 +10,16 @@
|
|
|
10
10
|
* turn is in flight it stops. Two buttons in one place was the thing every
|
|
11
11
|
* surface got subtly different.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* two SUB-composers, where it dismisses the thing they float over
|
|
16
|
-
* (`SelectionAsk.tsx:85`, `EditMessage.tsx:124`), which is the host's concern
|
|
17
|
-
* and not the field's. ARROWUP recalls the last turn in exactly one composer,
|
|
18
|
-
* chat's (`useHandleKeyUp.ts:117`), and it does it by finding
|
|
19
|
-
* `document.getElementById('edit-' + parentMessageId)` and clicking it — it is
|
|
20
|
-
* a binding to their edit-in-place, not a general history recall, and there is
|
|
21
|
-
* nothing here for it to reach. Adding either would be inventing an interaction
|
|
22
|
-
* and then asking three surfaces to adopt it.
|
|
13
|
+
* Escape and ArrowUp are not bound. Dismissal belongs to whatever the composer
|
|
14
|
+
* floats inside, and history recall needs a turn store this has no view of.
|
|
23
15
|
*
|
|
24
|
-
* Growth is `Textarea`'s
|
|
25
|
-
*
|
|
26
|
-
* raises the field instead of scrolling inside it. `rows` is the floor and
|
|
27
|
-
* `maxHeight` the ceiling; both are bounds, and neither is re-implemented here.
|
|
16
|
+
* Growth is `Textarea`'s and follows the content, so a wrapped paragraph raises
|
|
17
|
+
* the field. `rows` is the floor, `maxHeight` the ceiling.
|
|
28
18
|
*/
|
|
29
19
|
import { YStack } from '@hanzo/gui';
|
|
30
20
|
import type { ComponentProps, ReactNode } from 'react';
|
|
31
21
|
import { Textarea } from '../backends/gui/index.js';
|
|
32
|
-
/** `onChange` is dropped:
|
|
33
|
-
* draft, not a DOM change event. */
|
|
22
|
+
/** `onChange` is dropped: here it carries the draft, not a DOM change event. */
|
|
34
23
|
type Stack = Omit<ComponentProps<typeof YStack>, 'children' | 'onChange'>;
|
|
35
24
|
type FieldProps = Omit<ComponentProps<typeof Textarea>, 'value' | 'onChangeText'>;
|
|
36
25
|
/**
|
|
@@ -62,25 +51,17 @@ export interface ComposerProps extends Stack {
|
|
|
62
51
|
/** Hint shown at the end of the footer row. */
|
|
63
52
|
hint?: string;
|
|
64
53
|
/**
|
|
65
|
-
* The accessible name of the field
|
|
54
|
+
* The accessible name of the field, independent of `placeholder`.
|
|
66
55
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* writer was typing into it. The name is stable and the placeholder is
|
|
71
|
-
* decoration; deriving one from the other conflates them.
|
|
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.
|
|
72
59
|
*/
|
|
73
60
|
label?: string;
|
|
74
61
|
/** The field's own props — a ref, a testid, focus handlers, a paste handler. */
|
|
75
62
|
field?: FieldProps;
|
|
76
|
-
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* The default is the right one — one button that submits and stops, which is
|
|
80
|
-
* what every surface got subtly different — but a surface with a second
|
|
81
|
-
* commit mode has nowhere else to put it, and `children` is the START of the
|
|
82
|
-
* footer row.
|
|
83
|
-
*/
|
|
63
|
+
/** Replaces the send control. `children` is the START of the footer row, so a
|
|
64
|
+
* second commit mode has nowhere else to go. */
|
|
84
65
|
send?: ReactNode;
|
|
85
66
|
}
|
|
86
67
|
export declare function Composer({ value, onChange, onSend, onStop, busy, disabled, placeholder, rows, maxHeight, children, hint, label, field, send, ...props }: ComposerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -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":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAuB,MAAM,EAAE,MAAM,YAAY,CAAA;AAExD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAU,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAIlD,gFAAgF;AAChF,KAAK,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,CAAA;AACzE,KAAK,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,CAAA;AAajF;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,iBAAiB,CAAA;AAEjC,MAAM,WAAW,aAAc,SAAQ,KAAK;IAC1C,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,8EAA8E;IAC9E,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB;qDACiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,MAAM,EACN,MAAM,EACN,IAAY,EACZ,QAAgB,EAChB,WAAiB,EACjB,IAAe,EACf,SAAmB,EACnB,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,EACL,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,aAAa,2CAyEf"}
|
package/dist/chat/Composer.js
CHANGED
|
@@ -12,21 +12,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
12
12
|
* turn is in flight it stops. Two buttons in one place was the thing every
|
|
13
13
|
* surface got subtly different.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* two SUB-composers, where it dismisses the thing they float over
|
|
18
|
-
* (`SelectionAsk.tsx:85`, `EditMessage.tsx:124`), which is the host's concern
|
|
19
|
-
* and not the field's. ARROWUP recalls the last turn in exactly one composer,
|
|
20
|
-
* chat's (`useHandleKeyUp.ts:117`), and it does it by finding
|
|
21
|
-
* `document.getElementById('edit-' + parentMessageId)` and clicking it — it is
|
|
22
|
-
* a binding to their edit-in-place, not a general history recall, and there is
|
|
23
|
-
* nothing here for it to reach. Adding either would be inventing an interaction
|
|
24
|
-
* and then asking three surfaces to adopt it.
|
|
15
|
+
* Escape and ArrowUp are not bound. Dismissal belongs to whatever the composer
|
|
16
|
+
* floats inside, and history recall needs a turn store this has no view of.
|
|
25
17
|
*
|
|
26
|
-
* Growth is `Textarea`'s
|
|
27
|
-
*
|
|
28
|
-
* raises the field instead of scrolling inside it. `rows` is the floor and
|
|
29
|
-
* `maxHeight` the ceiling; both are bounds, and neither is re-implemented here.
|
|
18
|
+
* Growth is `Textarea`'s and follows the content, so a wrapped paragraph raises
|
|
19
|
+
* the field. `rows` is the floor, `maxHeight` the ceiling.
|
|
30
20
|
*/
|
|
31
21
|
import { SizableText, XStack, YStack } from '@hanzo/gui';
|
|
32
22
|
import { ArrowUp, Square } from '@hanzogui/lucide-icons-2';
|
|
@@ -35,34 +25,11 @@ import { slot } from '../backends/gui/slot.js';
|
|
|
35
25
|
import { ready, sends } from './send.js';
|
|
36
26
|
const PAD = 8;
|
|
37
27
|
const MIN_ROWS = 1;
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* 200 is the number three independent composers reached — hanzo.app `/chat`
|
|
42
|
-
* (`page.tsx:184`, `Math.min(el.scrollHeight, 200)`), hanzo/chat's
|
|
43
|
-
* `AnswerComposer.tsx:134`, and the extension's `answer/Composer.tsx:81`
|
|
44
|
-
* (`maxH={200}`). The two that differ are both fitting a NARROWER frame — the
|
|
45
|
-
* extension's in-page overlay caps at 110 (`content-script.ts:1340`) and its
|
|
46
|
-
* sidebar at 120 — and the one that differs upward, chat's main composer at
|
|
47
|
-
* `max-h-[45vh]`, is the full-page surface. So 200 is the default and the
|
|
48
|
-
* ceiling is a prop.
|
|
49
|
-
*
|
|
50
|
-
* Uncapped is not an option: the field would grow with the draft until a long
|
|
51
|
-
* paste owned the viewport and pushed the thread it belongs to off screen.
|
|
52
|
-
* Nothing capped it here before.
|
|
53
|
-
*/
|
|
28
|
+
/** How tall the field may grow before it scrolls, px. Uncapped, a long paste
|
|
29
|
+
* pushes the thread off screen; narrower frames pass their own. */
|
|
54
30
|
const CEILING = 200;
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* `Textarea` is a form control and stands 64px tall by default, which is right
|
|
59
|
-
* for a message body in a form and wrong for a composer: it is three lines of
|
|
60
|
-
* chrome before anything is typed. Every surface sets its own — 44 in chat
|
|
61
|
-
* (`ChatForm.tsx:334`) and in the app builder (`COMPOSER_MIN_H`), 48 in the app
|
|
62
|
-
* `/chat`. 44 is both the mode and this package's touch-target floor, so the
|
|
63
|
-
* one-line composer is exactly as tall as the smallest thing you are allowed to
|
|
64
|
-
* tap.
|
|
65
|
-
*/
|
|
31
|
+
/** Floor for the field, px. `Textarea` defaults to 64, which is three lines of
|
|
32
|
+
* chrome before anything is typed. 44 is the touch-target floor. */
|
|
66
33
|
const FLOOR = 44;
|
|
67
34
|
/**
|
|
68
35
|
* The resting placeholder.
|
|
@@ -94,11 +61,8 @@ export function Composer({ value, onChange, onSend, onStop, busy = false, disabl
|
|
|
94
61
|
onSend();
|
|
95
62
|
};
|
|
96
63
|
return (_jsxs(YStack, { ...slot('composer'), width: "100%", rounded: "$5", borderWidth: 1, borderColor: "$borderColor", bg: "$background", p: PAD, gap: PAD, ...props, children: [_jsx(Textarea, { ...slot('composer-field'), rows: rows, placeholder: placeholder, disabled: disabled, borderWidth: 0, minH: FLOOR, maxH: maxHeight, "aria-label": label ?? placeholder, ...field,
|
|
97
|
-
// After `field
|
|
98
|
-
//
|
|
99
|
-
// rule and the IME guard with it, type-check, and go on looking
|
|
100
|
-
// correct until a Japanese writer typed into it. So the caller's runs
|
|
101
|
-
// FIRST and this one defers to it if it claimed the key.
|
|
64
|
+
// After `field`: spread over, a caller's `onKeyDown` would replace the
|
|
65
|
+
// Enter rule and the IME guard. Theirs runs first and can claim the key.
|
|
102
66
|
value: value, onChangeText: onChange, onKeyDown: (e) => {
|
|
103
67
|
field?.onKeyDown?.(e);
|
|
104
68
|
if (!e?.defaultPrevented)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Composer.js","sourceRoot":"","sources":["../../src/chat/Composer.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ
|
|
1
|
+
{"version":3,"file":"Composer.js","sourceRoot":"","sources":["../../src/chat/Composer.tsx"],"names":[],"mappings":"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"}
|
package/dist/chat/Failure.cjs
CHANGED
|
@@ -4,29 +4,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.Failure = Failure;
|
|
5
5
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
6
|
/**
|
|
7
|
-
* Failure — the turn did not
|
|
7
|
+
* Failure — the turn did not arrive, and what to do about it.
|
|
8
8
|
*
|
|
9
9
|
* Distinct from a `Step` that errored: a step can fail inside an answer that
|
|
10
|
-
* still
|
|
11
|
-
*
|
|
12
|
-
* swapping the whole body for `ErrorMessage`.
|
|
10
|
+
* still lands. Retry sits beside the message, not in the hover strip, so it is
|
|
11
|
+
* reachable on a touch device.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* again" (`ask-ai/chat-thread.tsx:258`), the extension's `.ae-error` div
|
|
18
|
-
* (`AnswerEngine.tsx:336`), and hanzo.app `/chat`, which is the interesting
|
|
19
|
-
* one: it sets `Message.error` at `app/chat/page.tsx:292` and never reads it
|
|
20
|
-
* anywhere in the render, so a stream that dies reports through a detached
|
|
21
|
-
* banner and the turn itself says nothing.
|
|
22
|
-
*
|
|
23
|
-
* Two of the four offer a way to try again. Both put it next to the message
|
|
24
|
-
* rather than in the hover strip, because a hover affordance on the thing that
|
|
25
|
-
* just failed is not reachable on a touch device.
|
|
26
|
-
*
|
|
27
|
-
* `role="alert"` with `aria-live="assertive"` is chat's, and it is right: a
|
|
28
|
-
* turn failing is the one event in a conversation that has to interrupt, since
|
|
29
|
-
* the reader is waiting on prose that is never going to come.
|
|
13
|
+
* `role="alert"` with `aria-live="assertive"`: the reader is waiting on prose
|
|
14
|
+
* that is never coming, which is the one event in a conversation that has to
|
|
15
|
+
* interrupt.
|
|
30
16
|
*/
|
|
31
17
|
const gui_1 = require("@hanzo/gui");
|
|
32
18
|
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
@@ -35,14 +21,9 @@ const ink_1 = require("../backends/gui/ink.cjs");
|
|
|
35
21
|
const slot_1 = require("../backends/gui/slot.cjs");
|
|
36
22
|
function Failure({ children, onRetry, retryLabel = 'Try again', ...props }) {
|
|
37
23
|
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('failure'), role: "alert", "aria-live": "assertive", width: "100%", gap: "$2", px: "$3", py: "$2.5", rounded: "$4", borderWidth: 1,
|
|
38
|
-
// The
|
|
39
|
-
// `$color4` behind a `$color9` border for exactly this: with no hue to
|
|
40
|
-
// spend, an outline is what separates "this one" from its neighbours.
|
|
24
|
+
// The `stopped` register from `product/tone.ts`: an outline, not a hue.
|
|
41
25
|
borderColor: "$color9", bg: "$color4", ...props, children: [(0, ink_1.ink)(children, undefined, { size: '$2', color: '$color12' }), onRetry ? (
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
// because the activation behaviour belongs to the element and not to
|
|
45
|
-
// the attribute — and the one control on a failed turn is the last one
|
|
46
|
-
// that should be pointer-only.
|
|
26
|
+
// A real Button: a View wearing `role="button"` takes focus and then
|
|
27
|
+
// ignores Enter and Space.
|
|
47
28
|
(0, jsx_runtime_1.jsx)(gui_1.XStack, { self: "flex-start", children: (0, jsx_runtime_1.jsxs)(gui_2.Button, { ...(0, slot_1.slot)('failure-retry'), variant: "outline", size: "sm", onPress: onRetry, children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.RefreshCw, { size: 13 }), retryLabel] }) })) : null] }));
|
|
48
29
|
}
|
package/dist/chat/Failure.d.ts
CHANGED
|
@@ -1,27 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Failure — the turn did not
|
|
2
|
+
* Failure — the turn did not arrive, and what to do about it.
|
|
3
3
|
*
|
|
4
4
|
* Distinct from a `Step` that errored: a step can fail inside an answer that
|
|
5
|
-
* still
|
|
6
|
-
*
|
|
7
|
-
* swapping the whole body for `ErrorMessage`.
|
|
5
|
+
* still lands. Retry sits beside the message, not in the hover strip, so it is
|
|
6
|
+
* reachable on a touch device.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* again" (`ask-ai/chat-thread.tsx:258`), the extension's `.ae-error` div
|
|
13
|
-
* (`AnswerEngine.tsx:336`), and hanzo.app `/chat`, which is the interesting
|
|
14
|
-
* one: it sets `Message.error` at `app/chat/page.tsx:292` and never reads it
|
|
15
|
-
* anywhere in the render, so a stream that dies reports through a detached
|
|
16
|
-
* banner and the turn itself says nothing.
|
|
17
|
-
*
|
|
18
|
-
* Two of the four offer a way to try again. Both put it next to the message
|
|
19
|
-
* rather than in the hover strip, because a hover affordance on the thing that
|
|
20
|
-
* just failed is not reachable on a touch device.
|
|
21
|
-
*
|
|
22
|
-
* `role="alert"` with `aria-live="assertive"` is chat's, and it is right: a
|
|
23
|
-
* turn failing is the one event in a conversation that has to interrupt, since
|
|
24
|
-
* the reader is waiting on prose that is never going to come.
|
|
8
|
+
* `role="alert"` with `aria-live="assertive"`: the reader is waiting on prose
|
|
9
|
+
* that is never coming, which is the one event in a conversation that has to
|
|
10
|
+
* interrupt.
|
|
25
11
|
*/
|
|
26
12
|
import { YStack } from '@hanzo/gui';
|
|
27
13
|
import type { ComponentProps, ReactNode } from 'react';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Failure.d.ts","sourceRoot":"","sources":["../../src/chat/Failure.tsx"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"Failure.d.ts","sourceRoot":"","sources":["../../src/chat/Failure.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAU,MAAM,EAAE,MAAM,YAAY,CAAA;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtD,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC;IACnF,mDAAmD;IACnD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAwB,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY,2CA8B9F"}
|
package/dist/chat/Failure.js
CHANGED
|
@@ -1,29 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* Failure — the turn did not
|
|
4
|
+
* Failure — the turn did not arrive, and what to do about it.
|
|
5
5
|
*
|
|
6
6
|
* Distinct from a `Step` that errored: a step can fail inside an answer that
|
|
7
|
-
* still
|
|
8
|
-
*
|
|
9
|
-
* swapping the whole body for `ErrorMessage`.
|
|
7
|
+
* still lands. Retry sits beside the message, not in the hover strip, so it is
|
|
8
|
+
* reachable on a touch device.
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* again" (`ask-ai/chat-thread.tsx:258`), the extension's `.ae-error` div
|
|
15
|
-
* (`AnswerEngine.tsx:336`), and hanzo.app `/chat`, which is the interesting
|
|
16
|
-
* one: it sets `Message.error` at `app/chat/page.tsx:292` and never reads it
|
|
17
|
-
* anywhere in the render, so a stream that dies reports through a detached
|
|
18
|
-
* banner and the turn itself says nothing.
|
|
19
|
-
*
|
|
20
|
-
* Two of the four offer a way to try again. Both put it next to the message
|
|
21
|
-
* rather than in the hover strip, because a hover affordance on the thing that
|
|
22
|
-
* just failed is not reachable on a touch device.
|
|
23
|
-
*
|
|
24
|
-
* `role="alert"` with `aria-live="assertive"` is chat's, and it is right: a
|
|
25
|
-
* turn failing is the one event in a conversation that has to interrupt, since
|
|
26
|
-
* the reader is waiting on prose that is never going to come.
|
|
10
|
+
* `role="alert"` with `aria-live="assertive"`: the reader is waiting on prose
|
|
11
|
+
* that is never coming, which is the one event in a conversation that has to
|
|
12
|
+
* interrupt.
|
|
27
13
|
*/
|
|
28
14
|
import { XStack, YStack } from '@hanzo/gui';
|
|
29
15
|
import { RefreshCw } from '@hanzogui/lucide-icons-2';
|
|
@@ -32,15 +18,10 @@ import { ink } from '../backends/gui/ink.js';
|
|
|
32
18
|
import { slot } from '../backends/gui/slot.js';
|
|
33
19
|
export function Failure({ children, onRetry, retryLabel = 'Try again', ...props }) {
|
|
34
20
|
return (_jsxs(YStack, { ...slot('failure'), role: "alert", "aria-live": "assertive", width: "100%", gap: "$2", px: "$3", py: "$2.5", rounded: "$4", borderWidth: 1,
|
|
35
|
-
// The
|
|
36
|
-
// `$color4` behind a `$color9` border for exactly this: with no hue to
|
|
37
|
-
// spend, an outline is what separates "this one" from its neighbours.
|
|
21
|
+
// The `stopped` register from `product/tone.ts`: an outline, not a hue.
|
|
38
22
|
borderColor: "$color9", bg: "$color4", ...props, children: [ink(children, undefined, { size: '$2', color: '$color12' }), onRetry ? (
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
// because the activation behaviour belongs to the element and not to
|
|
42
|
-
// the attribute — and the one control on a failed turn is the last one
|
|
43
|
-
// that should be pointer-only.
|
|
23
|
+
// A real Button: a View wearing `role="button"` takes focus and then
|
|
24
|
+
// ignores Enter and Space.
|
|
44
25
|
_jsx(XStack, { self: "flex-start", children: _jsxs(Button, { ...slot('failure-retry'), variant: "outline", size: "sm", onPress: onRetry, children: [_jsx(RefreshCw, { size: 13 }), retryLabel] }) })) : null] }));
|
|
45
26
|
}
|
|
46
27
|
//# sourceMappingURL=Failure.js.map
|
package/dist/chat/Failure.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Failure.js","sourceRoot":"","sources":["../../src/chat/Failure.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ
|
|
1
|
+
{"version":3,"file":"Failure.js","sourceRoot":"","sources":["../../src/chat/Failure.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAGpD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAU3C,MAAM,UAAU,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,GAAG,WAAW,EAAE,GAAG,KAAK,EAAgB;IAC7F,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,SAAS,CAAC,EACnB,IAAI,EAAC,OAAO,eACF,WAAW,EACrB,KAAK,EAAC,MAAM,EACZ,GAAG,EAAC,IAAI,EACR,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,MAAM,EACT,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC;QACd,wEAAwE;QACxE,WAAW,EAAC,SAAS,EACrB,EAAE,EAAC,SAAS,KACR,KAAK,aAER,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAC3D,OAAO,CAAC,CAAC,CAAC;YACT,qEAAqE;YACrE,2BAA2B;YAC3B,KAAC,MAAM,IAAC,IAAI,EAAC,YAAY,YACvB,MAAC,MAAM,OAAK,IAAI,CAAC,eAAe,CAAC,EAAE,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,OAAO,aAC7E,KAAC,SAAS,IAAC,IAAI,EAAE,EAAE,GAAI,EACtB,UAAU,IACJ,GACF,CACV,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAA;AACH,CAAC"}
|