@particle-academy/react-fancy 5.37.0 → 5.39.0
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/CHANGELOG.md +133 -0
- package/dist/{index-C8PKWA_5.d.cts → Composer.types-CuSPnaOt.d.cts} +103 -7
- package/dist/{index-C8PKWA_5.d.ts → Composer.types-CuSPnaOt.d.ts} +103 -7
- package/dist/autocomplete.cjs +3 -3
- package/dist/autocomplete.js +2 -2
- package/dist/chunk-2JOWGYAJ.js +609 -0
- package/dist/chunk-2JOWGYAJ.js.map +1 -0
- package/dist/chunk-6TZPM43Q.cjs +616 -0
- package/dist/chunk-6TZPM43Q.cjs.map +1 -0
- package/dist/{chunk-FXP4JLGU.cjs → chunk-AR3JOPGT.cjs} +3 -3
- package/dist/{chunk-FXP4JLGU.cjs.map → chunk-AR3JOPGT.cjs.map} +1 -1
- package/dist/{chunk-23FTDEGR.cjs → chunk-BZOU7VJQ.cjs} +97 -84
- package/dist/chunk-BZOU7VJQ.cjs.map +1 -0
- package/dist/{chunk-35EN5AYE.js → chunk-CF5KRDN4.js} +6 -3
- package/dist/chunk-CF5KRDN4.js.map +1 -0
- package/dist/{chunk-DNV7MUEE.cjs → chunk-FJ2GMQLC.cjs} +117 -27
- package/dist/chunk-FJ2GMQLC.cjs.map +1 -0
- package/dist/{chunk-6ASZUE4T.js → chunk-FQLL2JI7.js} +3 -3
- package/dist/{chunk-6ASZUE4T.js.map → chunk-FQLL2JI7.js.map} +1 -1
- package/dist/{chunk-ZH3SPBVB.js → chunk-IECPLOSZ.js} +3 -3
- package/dist/{chunk-ZH3SPBVB.js.map → chunk-IECPLOSZ.js.map} +1 -1
- package/dist/{chunk-E2SZBIAV.cjs → chunk-IWQ3ZFLZ.cjs} +5 -5
- package/dist/{chunk-E2SZBIAV.cjs.map → chunk-IWQ3ZFLZ.cjs.map} +1 -1
- package/dist/{chunk-QBNR5IVM.cjs → chunk-MFBUK4RV.cjs} +3 -3
- package/dist/{chunk-QBNR5IVM.cjs.map → chunk-MFBUK4RV.cjs.map} +1 -1
- package/dist/{chunk-2XAVAPDA.js → chunk-MXAVGOHW.js} +99 -85
- package/dist/chunk-MXAVGOHW.js.map +1 -0
- package/dist/{chunk-ISPCXIJZ.cjs → chunk-X7H75WVP.cjs} +6 -3
- package/dist/chunk-X7H75WVP.cjs.map +1 -0
- package/dist/{chunk-O3WEV562.js → chunk-YLPVTEUH.js} +118 -28
- package/dist/chunk-YLPVTEUH.js.map +1 -0
- package/dist/{chunk-O2ZHORSC.js → chunk-Z6RVBZQ4.js} +3 -3
- package/dist/{chunk-O2ZHORSC.js.map → chunk-Z6RVBZQ4.js.map} +1 -1
- package/dist/composer.cjs +10 -2
- package/dist/composer.d.cts +7 -2
- package/dist/composer.d.ts +7 -2
- package/dist/composer.js +5 -1
- package/dist/editor.cjs +1 -1
- package/dist/editor.js +1 -1
- package/dist/{index-DXUAAZzE.d.ts → index-BsIBOwaK.d.cts} +46 -1
- package/dist/{index-DXUAAZzE.d.cts → index-S4FC1yFK.d.ts} +46 -1
- package/dist/index.cjs +40 -35
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +8 -7
- package/dist/inputs.cjs +3 -3
- package/dist/inputs.js +2 -2
- package/dist/json-editor.cjs +14 -14
- package/dist/json-editor.js +3 -3
- package/dist/prompt-input.cjs +5 -3
- package/dist/prompt-input.d.cts +2 -1
- package/dist/prompt-input.d.ts +2 -1
- package/dist/prompt-input.js +4 -2
- package/dist/select.cjs +3 -3
- package/dist/select.js +2 -2
- package/dist/tooltip.cjs +2 -2
- package/dist/tooltip.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-23FTDEGR.cjs.map +0 -1
- package/dist/chunk-2XAVAPDA.js.map +0 -1
- package/dist/chunk-35EN5AYE.js.map +0 -1
- package/dist/chunk-DNV7MUEE.cjs.map +0 -1
- package/dist/chunk-ISPCXIJZ.cjs.map +0 -1
- package/dist/chunk-O3WEV562.js.map +0 -1
|
@@ -1,58 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunk6TZPM43Q_cjs = require('./chunk-6TZPM43Q.cjs');
|
|
3
4
|
var chunkSNHU2AI4_cjs = require('./chunk-SNHU2AI4.cjs');
|
|
4
5
|
var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
|
|
5
6
|
var react = require('react');
|
|
6
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
8
|
|
|
8
|
-
function usePastePills({
|
|
9
|
-
threshold,
|
|
10
|
-
heldPastes: controlledHeldPastes,
|
|
11
|
-
onHeldPastesChange
|
|
12
|
-
} = {}) {
|
|
13
|
-
const [heldPastes, setHeldPastes] = chunkSNHU2AI4_cjs.useControllableState(
|
|
14
|
-
controlledHeldPastes,
|
|
15
|
-
[],
|
|
16
|
-
onHeldPastesChange
|
|
17
|
-
);
|
|
18
|
-
const nextId = react.useRef(0);
|
|
19
|
-
const handlePaste = react.useCallback(
|
|
20
|
-
(event) => {
|
|
21
|
-
if (!threshold || threshold <= 0) return false;
|
|
22
|
-
const text = event.clipboardData?.getData("text/plain") ?? "";
|
|
23
|
-
if (text.length < threshold) return false;
|
|
24
|
-
event.preventDefault();
|
|
25
|
-
nextId.current += 1;
|
|
26
|
-
const id = `paste-${nextId.current}`;
|
|
27
|
-
setHeldPastes((current) => [...current, { id, text }]);
|
|
28
|
-
return true;
|
|
29
|
-
},
|
|
30
|
-
[threshold, setHeldPastes]
|
|
31
|
-
);
|
|
32
|
-
const expand = react.useCallback(
|
|
33
|
-
(id) => {
|
|
34
|
-
const found = heldPastes.find((p) => p.id === id);
|
|
35
|
-
if (found === void 0) return void 0;
|
|
36
|
-
setHeldPastes((current) => current.filter((p) => p.id !== id));
|
|
37
|
-
return found.text;
|
|
38
|
-
},
|
|
39
|
-
[heldPastes, setHeldPastes]
|
|
40
|
-
);
|
|
41
|
-
const remove = react.useCallback(
|
|
42
|
-
(id) => setHeldPastes((current) => current.filter((p) => p.id !== id)),
|
|
43
|
-
[setHeldPastes]
|
|
44
|
-
);
|
|
45
|
-
const clear = react.useCallback(() => setHeldPastes([]), [setHeldPastes]);
|
|
46
|
-
return { heldPastes, handlePaste, expand, remove, clear };
|
|
47
|
-
}
|
|
48
9
|
var PREVIEW_CHARS = 20;
|
|
49
|
-
function withSeparators(n) {
|
|
50
|
-
return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
51
|
-
}
|
|
52
|
-
function endsOf(text) {
|
|
53
|
-
if (text.length <= PREVIEW_CHARS * 2) return text;
|
|
54
|
-
return `${text.slice(0, PREVIEW_CHARS)} \u2026 ${text.slice(-PREVIEW_CHARS)}`;
|
|
55
|
-
}
|
|
56
10
|
var Composer = react.forwardRef(
|
|
57
11
|
function Composer2({
|
|
58
12
|
value: controlledValue,
|
|
@@ -64,39 +18,69 @@ var Composer = react.forwardRef(
|
|
|
64
18
|
disabled = false,
|
|
65
19
|
className,
|
|
66
20
|
pasteThreshold,
|
|
21
|
+
pastePlacement = "above",
|
|
22
|
+
pasteImages = false,
|
|
23
|
+
previewChars = PREVIEW_CHARS,
|
|
24
|
+
renderPastePreview,
|
|
25
|
+
classNames,
|
|
67
26
|
heldPastes: controlledHeldPastes,
|
|
68
|
-
onHeldPastesChange
|
|
27
|
+
onHeldPastesChange,
|
|
28
|
+
heldImages: controlledHeldImages,
|
|
29
|
+
onHeldImagesChange
|
|
69
30
|
}, ref) {
|
|
31
|
+
const inline = pastePlacement === "inline";
|
|
70
32
|
const [value, setValue] = chunkSNHU2AI4_cjs.useControllableState(
|
|
71
33
|
controlledValue,
|
|
72
34
|
defaultValue,
|
|
73
35
|
onChange
|
|
74
36
|
);
|
|
75
|
-
const
|
|
76
|
-
|
|
37
|
+
const textareaRef = react.useRef(null);
|
|
38
|
+
const editorRef = react.useRef(null);
|
|
39
|
+
const paste = chunk6TZPM43Q_cjs.useInlinePaste({
|
|
40
|
+
pasteThreshold,
|
|
41
|
+
pasteImages,
|
|
42
|
+
previewChars,
|
|
43
|
+
renderPastePreview,
|
|
44
|
+
classNames,
|
|
45
|
+
disabled,
|
|
77
46
|
heldPastes: controlledHeldPastes,
|
|
78
|
-
onHeldPastesChange
|
|
47
|
+
onHeldPastesChange,
|
|
48
|
+
heldImages: controlledHeldImages,
|
|
49
|
+
onHeldImagesChange,
|
|
50
|
+
editorRef
|
|
79
51
|
});
|
|
80
|
-
const
|
|
81
|
-
const
|
|
52
|
+
const pills = paste.pills;
|
|
53
|
+
const heldPastes = paste.heldPastes;
|
|
82
54
|
const handlePaste = react.useCallback(
|
|
83
55
|
(e) => {
|
|
84
56
|
pills.handlePaste(e);
|
|
85
57
|
},
|
|
86
58
|
[pills]
|
|
87
59
|
);
|
|
88
|
-
const
|
|
89
|
-
() =>
|
|
90
|
-
|
|
60
|
+
const handleInlineChange = react.useCallback(
|
|
61
|
+
(next) => {
|
|
62
|
+
setValue(next);
|
|
63
|
+
paste.prune(next);
|
|
64
|
+
},
|
|
65
|
+
[setValue, paste]
|
|
91
66
|
);
|
|
92
|
-
const
|
|
67
|
+
const composeOutgoing = react.useCallback(() => {
|
|
68
|
+
if (inline) return paste.expand(value);
|
|
69
|
+
return [value, ...heldPastes.map((p) => p.text)].filter(Boolean).join("\n\n");
|
|
70
|
+
}, [inline, value, heldPastes, paste]);
|
|
71
|
+
const hasContent = value.trim().length > 0 || !inline && heldPastes.length > 0;
|
|
72
|
+
const focusInput = react.useCallback(() => {
|
|
73
|
+
if (inline) editorRef.current?.focus();
|
|
74
|
+
else textareaRef.current?.focus();
|
|
75
|
+
}, [inline]);
|
|
93
76
|
const handleSubmit = react.useCallback(() => {
|
|
94
77
|
if (!hasContent || disabled) return;
|
|
95
|
-
|
|
78
|
+
const images = inline ? paste.imagesIn(value) : [];
|
|
79
|
+
onSubmit?.(composeOutgoing(), { images });
|
|
96
80
|
setValue("");
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}, [hasContent, disabled, onSubmit, composeOutgoing, setValue,
|
|
81
|
+
paste.clear();
|
|
82
|
+
focusInput();
|
|
83
|
+
}, [hasContent, disabled, value, inline, paste, onSubmit, composeOutgoing, setValue, focusInput]);
|
|
100
84
|
const handleKeyDown = (e) => {
|
|
101
85
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
102
86
|
e.preventDefault();
|
|
@@ -104,8 +88,8 @@ var Composer = react.forwardRef(
|
|
|
104
88
|
}
|
|
105
89
|
};
|
|
106
90
|
const insertPaste = react.useCallback(
|
|
107
|
-
(
|
|
108
|
-
const text = pills.expand(
|
|
91
|
+
(held) => {
|
|
92
|
+
const text = pills.expand(held.id);
|
|
109
93
|
if (text === void 0) return;
|
|
110
94
|
setValue((current) => current ? `${current}
|
|
111
95
|
|
|
@@ -125,12 +109,12 @@ ${text}` : text);
|
|
|
125
109
|
className
|
|
126
110
|
),
|
|
127
111
|
children: [
|
|
128
|
-
heldPastes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
112
|
+
!inline && heldPastes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
129
113
|
"div",
|
|
130
114
|
{
|
|
131
115
|
"data-react-fancy-composer-paste-pills": "",
|
|
132
116
|
className: "flex flex-wrap gap-1.5 px-3 pt-3",
|
|
133
|
-
children: heldPastes.map((
|
|
117
|
+
children: heldPastes.map((paste2) => (
|
|
134
118
|
// `group` + `group-hover` rather than hover state: the preview is
|
|
135
119
|
// presentation, and a useState for it would be one more thing an
|
|
136
120
|
// agent could desynchronise.
|
|
@@ -139,15 +123,19 @@ ${text}` : text);
|
|
|
139
123
|
"button",
|
|
140
124
|
{
|
|
141
125
|
type: "button",
|
|
142
|
-
"data-react-fancy-composer-paste-pill":
|
|
143
|
-
onClick: () => insertPaste(
|
|
126
|
+
"data-react-fancy-composer-paste-pill": paste2.id,
|
|
127
|
+
onClick: () => insertPaste(paste2),
|
|
144
128
|
disabled,
|
|
145
|
-
"aria-label": `Insert this pasted text, ${withSeparators(
|
|
146
|
-
"aria-describedby": `${
|
|
147
|
-
className:
|
|
129
|
+
"aria-label": `Insert this pasted text, ${chunk6TZPM43Q_cjs.withSeparators(paste2.text.length)} characters`,
|
|
130
|
+
"aria-describedby": `${paste2.id}-preview`,
|
|
131
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
132
|
+
"inline-flex items-center gap-1.5 rounded-full border border-zinc-200 bg-zinc-50 py-1 pl-2.5 pr-7 text-xs text-zinc-700 transition-colors hover:bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200 dark:hover:bg-zinc-700",
|
|
133
|
+
classNames?.pill,
|
|
134
|
+
classNames?.textPill
|
|
135
|
+
),
|
|
148
136
|
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
149
137
|
"Pasted text \xB7 ",
|
|
150
|
-
withSeparators(
|
|
138
|
+
chunk6TZPM43Q_cjs.withSeparators(paste2.text.length),
|
|
151
139
|
" characters"
|
|
152
140
|
] })
|
|
153
141
|
}
|
|
@@ -156,29 +144,52 @@ ${text}` : text);
|
|
|
156
144
|
"button",
|
|
157
145
|
{
|
|
158
146
|
type: "button",
|
|
159
|
-
"data-react-fancy-composer-paste-pill-remove":
|
|
160
|
-
onClick: () => pills.remove(
|
|
147
|
+
"data-react-fancy-composer-paste-pill-remove": paste2.id,
|
|
148
|
+
onClick: () => pills.remove(paste2.id),
|
|
161
149
|
disabled,
|
|
162
150
|
"aria-label": "Discard this pasted text",
|
|
163
|
-
className:
|
|
151
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
152
|
+
"absolute right-1 top-1/2 -translate-y-1/2 rounded-full px-1 text-xs text-zinc-400 transition-colors hover:text-zinc-700 dark:hover:text-zinc-100",
|
|
153
|
+
classNames?.remove
|
|
154
|
+
),
|
|
164
155
|
children: "\xD7"
|
|
165
156
|
}
|
|
166
157
|
),
|
|
167
158
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
168
159
|
"span",
|
|
169
160
|
{
|
|
170
|
-
id: `${
|
|
171
|
-
"data-react-fancy-composer-paste-pill-preview":
|
|
161
|
+
id: `${paste2.id}-preview`,
|
|
162
|
+
"data-react-fancy-composer-paste-pill-preview": paste2.id,
|
|
172
163
|
role: "tooltip",
|
|
173
|
-
className:
|
|
174
|
-
|
|
164
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
165
|
+
"pointer-events-none absolute bottom-full left-0 z-10 mb-1 hidden max-w-xs whitespace-pre-wrap break-all rounded-md bg-zinc-900 px-2 py-1 text-xs text-white group-hover:block dark:bg-zinc-100 dark:text-zinc-900",
|
|
166
|
+
classNames?.preview
|
|
167
|
+
),
|
|
168
|
+
children: renderPastePreview?.({ kind: "text", paste: paste2 }) ?? chunk6TZPM43Q_cjs.endsOf(paste2.text, previewChars)
|
|
175
169
|
}
|
|
176
170
|
)
|
|
177
|
-
] },
|
|
171
|
+
] }, paste2.id)
|
|
178
172
|
))
|
|
179
173
|
}
|
|
180
174
|
),
|
|
181
|
-
/* @__PURE__ */ jsxRuntime.
|
|
175
|
+
inline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
177
|
+
chunk6TZPM43Q_cjs.InlinePasteEditor,
|
|
178
|
+
{
|
|
179
|
+
ref: editorRef,
|
|
180
|
+
value,
|
|
181
|
+
known: paste.known,
|
|
182
|
+
onChange: handleInlineChange,
|
|
183
|
+
onSubmit: handleSubmit,
|
|
184
|
+
onPaste: paste.decidePaste,
|
|
185
|
+
onHostsChange: paste.onHostsChange,
|
|
186
|
+
placeholder,
|
|
187
|
+
disabled,
|
|
188
|
+
className: classNames?.input
|
|
189
|
+
}
|
|
190
|
+
),
|
|
191
|
+
paste.portals
|
|
192
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
182
193
|
"textarea",
|
|
183
194
|
{
|
|
184
195
|
ref: textareaRef,
|
|
@@ -189,7 +200,10 @@ ${text}` : text);
|
|
|
189
200
|
placeholder,
|
|
190
201
|
disabled,
|
|
191
202
|
rows: 3,
|
|
192
|
-
className:
|
|
203
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
204
|
+
"w-full resize-none bg-transparent px-4 pt-3 text-sm outline-none placeholder:text-zinc-400",
|
|
205
|
+
classNames?.input
|
|
206
|
+
)
|
|
193
207
|
}
|
|
194
208
|
),
|
|
195
209
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-t border-zinc-100 px-3 py-2 dark:border-zinc-800", children: [
|
|
@@ -213,6 +227,5 @@ ${text}` : text);
|
|
|
213
227
|
Composer.displayName = "Composer";
|
|
214
228
|
|
|
215
229
|
exports.Composer = Composer;
|
|
216
|
-
|
|
217
|
-
//# sourceMappingURL=chunk-
|
|
218
|
-
//# sourceMappingURL=chunk-23FTDEGR.cjs.map
|
|
230
|
+
//# sourceMappingURL=chunk-BZOU7VJQ.cjs.map
|
|
231
|
+
//# sourceMappingURL=chunk-BZOU7VJQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Composer/Composer.tsx"],"names":["forwardRef","Composer","useControllableState","useRef","useInlinePaste","useCallback","jsxs","cn","jsx","paste","withSeparators","endsOf","Fragment","InlinePasteEditor"],"mappings":"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","file":"chunk-BZOU7VJQ.cjs","sourcesContent":["import { forwardRef, useCallback, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { HeldPaste } from \"../../hooks/use-paste-pills\";\nimport { endsOf, withSeparators } from \"./InlinePill\";\nimport { InlinePasteEditor, type InlinePasteEditorHandle } from \"./InlinePasteEditor\";\nimport { useInlinePaste } from \"./use-inline-paste\";\nimport type { ComposerProps } from \"./Composer.types\";\n\n/** Characters of a held paste shown at each end of the hover preview, unless `previewChars` says otherwise. */\nconst PREVIEW_CHARS = 20;\n\nexport const Composer = forwardRef<HTMLDivElement, ComposerProps>(\n function Composer(\n {\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n onSubmit,\n placeholder = \"Type a message...\",\n actions,\n disabled = false,\n className,\n pasteThreshold,\n pastePlacement = \"above\",\n pasteImages = false,\n previewChars = PREVIEW_CHARS,\n renderPastePreview,\n classNames,\n heldPastes: controlledHeldPastes,\n onHeldPastesChange,\n heldImages: controlledHeldImages,\n onHeldImagesChange,\n },\n ref,\n ) {\n const inline = pastePlacement === \"inline\";\n const [value, setValue] = useControllableState(\n controlledValue,\n defaultValue,\n onChange,\n );\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const editorRef = useRef<InlinePasteEditorHandle>(null);\n /*\n * The holding logic lives in `usePastePills`, wrapped by `useInlinePaste` for\n * the inline placement — which `PromptInput` shares, so the two components\n * cannot disagree about what a pill means. The rule that must not drift is\n * the one below: a send with pills still closed carries the text.\n */\n const paste = useInlinePaste({\n pasteThreshold,\n pasteImages,\n previewChars,\n renderPastePreview,\n classNames,\n disabled,\n heldPastes: controlledHeldPastes,\n onHeldPastesChange,\n heldImages: controlledHeldImages,\n onHeldImagesChange,\n editorRef,\n });\n const pills = paste.pills;\n const heldPastes = paste.heldPastes;\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n // Composable by design, so this reads as a question rather than a handover.\n // Nothing else here wants the paste, so the answer is simply ignored.\n pills.handlePaste(e);\n },\n [pills],\n );\n\n const handleInlineChange = useCallback(\n (next: string) => {\n setValue(next);\n paste.prune(next);\n },\n [setValue, paste],\n );\n\n /** Everything the person believes they are sending, in the order they built it. */\n const composeOutgoing = useCallback(() => {\n if (inline) return paste.expand(value);\n\n return [value, ...heldPastes.map((p) => p.text)].filter(Boolean).join(\"\\n\\n\");\n }, [inline, value, heldPastes, paste]);\n\n const hasContent = value.trim().length > 0 || (!inline && heldPastes.length > 0);\n\n const focusInput = useCallback(() => {\n if (inline) editorRef.current?.focus();\n else textareaRef.current?.focus();\n }, [inline]);\n\n const handleSubmit = useCallback(() => {\n if (!hasContent || disabled) return;\n\n /*\n * THE DANGEROUS STATE, and the reason this feature needed a spec rather than\n * a guess. A pill reads as \"your paste is attached\" — so a send that drops it\n * means asking a question about a document without the document, and nobody\n * can tell: the sender believes it went, the receiver sees a question about\n * nothing.\n *\n * Above the input, held pastes go out in arrival order after what was typed,\n * because people type the question BEFORE pasting the thing it is about.\n * Inline, every pill goes out exactly where it sits.\n */\n const images = inline ? paste.imagesIn(value) : [];\n\n onSubmit?.(composeOutgoing(), { images });\n setValue(\"\");\n paste.clear();\n focusInput();\n }, [hasContent, disabled, value, inline, paste, onSubmit, composeOutgoing, setValue, focusInput]);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n /** Above the input: click a pill to dump it in, APPENDED to what is already typed. */\n const insertPaste = useCallback(\n (held: HeldPaste) => {\n // `expand` removes it and hands back the text; inserting is this\n // component's job because the hook owns no DOM.\n const text = pills.expand(held.id);\n\n if (text === undefined) return;\n\n setValue((current) => (current ? `${current}\\n\\n${text}` : text));\n textareaRef.current?.focus();\n },\n [pills, setValue],\n );\n\n return (\n <div\n data-react-fancy-composer=\"\"\n ref={ref}\n className={cn(\n \"rounded-xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900\",\n disabled && \"opacity-50\",\n className,\n )}\n >\n {!inline && heldPastes.length > 0 && (\n <div\n data-react-fancy-composer-paste-pills=\"\"\n className=\"flex flex-wrap gap-1.5 px-3 pt-3\"\n >\n {heldPastes.map((paste) => (\n // `group` + `group-hover` rather than hover state: the preview is\n // presentation, and a useState for it would be one more thing an\n // agent could desynchronise.\n <span key={paste.id} className=\"group relative inline-flex\">\n <button\n type=\"button\"\n data-react-fancy-composer-paste-pill={paste.id}\n onClick={() => insertPaste(paste)}\n disabled={disabled}\n // No `title`. A native tooltip plus the hover preview below\n // renders TWO tooltips on the same hover, at different delays.\n // The label says what clicking does; the preview says what the\n // text is, and it is linked rather than merely adjacent so a\n // screen reader reaches it too.\n aria-label={`Insert this pasted text, ${withSeparators(paste.text.length)} characters`}\n aria-describedby={`${paste.id}-preview`}\n // `pr-7` leaves room for the absolutely-positioned × that sits\n // over this button's right edge. With a smaller right padding the\n // × lands on top of the label.\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full border border-zinc-200 bg-zinc-50 py-1 pl-2.5 pr-7 text-xs text-zinc-700 transition-colors hover:bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200 dark:hover:bg-zinc-700\",\n classNames?.pill,\n classNames?.textPill,\n )}\n >\n <span>\n Pasted text · {withSeparators(paste.text.length)} characters\n </span>\n </button>\n\n <button\n type=\"button\"\n data-react-fancy-composer-paste-pill-remove={paste.id}\n onClick={() => pills.remove(paste.id)}\n disabled={disabled}\n aria-label=\"Discard this pasted text\"\n className={cn(\n \"absolute right-1 top-1/2 -translate-y-1/2 rounded-full px-1 text-xs text-zinc-400 transition-colors hover:text-zinc-700 dark:hover:text-zinc-100\",\n classNames?.remove,\n )}\n >\n ×\n </button>\n\n <span\n id={`${paste.id}-preview`}\n data-react-fancy-composer-paste-pill-preview={paste.id}\n role=\"tooltip\"\n className={cn(\n \"pointer-events-none absolute bottom-full left-0 z-10 mb-1 hidden max-w-xs whitespace-pre-wrap break-all rounded-md bg-zinc-900 px-2 py-1 text-xs text-white group-hover:block dark:bg-zinc-100 dark:text-zinc-900\",\n classNames?.preview,\n )}\n >\n {renderPastePreview?.({ kind: \"text\", paste }) ??\n endsOf(paste.text, previewChars)}\n </span>\n </span>\n ))}\n </div>\n )}\n\n {inline ? (\n <>\n <InlinePasteEditor\n ref={editorRef}\n value={value}\n known={paste.known}\n onChange={handleInlineChange}\n onSubmit={handleSubmit}\n onPaste={paste.decidePaste}\n onHostsChange={paste.onHostsChange}\n placeholder={placeholder}\n disabled={disabled}\n className={classNames?.input}\n />\n {paste.portals}\n </>\n ) : (\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n disabled={disabled}\n rows={3}\n className={cn(\n \"w-full resize-none bg-transparent px-4 pt-3 text-sm outline-none placeholder:text-zinc-400\",\n classNames?.input,\n )}\n />\n )}\n <div className=\"flex items-center justify-between border-t border-zinc-100 px-3 py-2 dark:border-zinc-800\">\n <div className=\"flex items-center gap-1\">{actions}</div>\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={disabled || !hasContent}\n className=\"rounded-lg bg-zinc-900 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-zinc-800 disabled:opacity-50 dark:bg-white dark:text-zinc-900 dark:hover:bg-zinc-100\"\n >\n Send\n </button>\n </div>\n </div>\n );\n },\n);\n\nComposer.displayName = \"Composer\";\n"]}
|
|
@@ -48,7 +48,10 @@ var Tooltip = forwardRef(
|
|
|
48
48
|
"div",
|
|
49
49
|
{
|
|
50
50
|
className: cn(
|
|
51
|
-
|
|
51
|
+
// `bg-inherit`, not a colour of its own: a `className` that
|
|
52
|
+
// restyles the bubble would otherwise leave a dark arrow
|
|
53
|
+
// pointing out of a light one.
|
|
54
|
+
"absolute h-2 w-2 rotate-45 bg-inherit",
|
|
52
55
|
position.placement.startsWith("top") && "bottom-[-4px] left-1/2 -translate-x-1/2",
|
|
53
56
|
position.placement.startsWith("bottom") && "top-[-4px] left-1/2 -translate-x-1/2",
|
|
54
57
|
position.placement.startsWith("left") && "right-[-4px] top-1/2 -translate-y-1/2",
|
|
@@ -65,5 +68,5 @@ var Tooltip = forwardRef(
|
|
|
65
68
|
Tooltip.displayName = "Tooltip";
|
|
66
69
|
|
|
67
70
|
export { Tooltip };
|
|
68
|
-
//# sourceMappingURL=chunk-
|
|
69
|
-
//# sourceMappingURL=chunk-
|
|
71
|
+
//# sourceMappingURL=chunk-CF5KRDN4.js.map
|
|
72
|
+
//# sourceMappingURL=chunk-CF5KRDN4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Tooltip/Tooltip.tsx"],"names":["Tooltip"],"mappings":";;;;;;AAaO,IAAM,OAAA,GAAU,UAAA;AAAA,EACrB,SAASA,QAAAA,CACP,EAAE,QAAA,EAAU,OAAA,EAAS,SAAA,GAAY,KAAA,EAAO,KAAA,GAAQ,GAAA,EAAK,MAAA,GAAS,CAAA,EAAG,SAAA,IACjE,IAAA,EACA;AACA,IAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,KAAK,CAAA;AACtC,IAAA,MAAM,SAAA,GAAY,OAAoB,IAAI,CAAA;AAC1C,IAAA,MAAM,WAAA,GAAc,OAAuB,IAAI,CAAA;AAC/C,IAAA,MAAM,UAAA,GAAa,OAAsC,MAAS,CAAA;AAElE,IAAA,MAAM,QAAA,GAAW,mBAAA,CAAoB,SAAA,EAAW,WAAA,EAAa;AAAA,MAC3D,SAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA,EAAS;AAAA,KACV,CAAA;AAED,IAAA,MAAM,IAAA,GAAO,YAAY,MAAM;AAC7B,MAAA,UAAA,CAAW,UAAU,UAAA,CAAW,MAAM,OAAA,CAAQ,IAAI,GAAG,KAAK,CAAA;AAAA,IAC5D,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,IAAA,MAAM,IAAA,GAAO,YAAY,MAAM;AAC7B,MAAA,YAAA,CAAa,WAAW,OAAO,CAAA;AAC/B,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf,CAAA,EAAG,EAAE,CAAA;AAEL,IAAA,MAAM,OAAA,GAAU,aAAa,QAAA,EAAmD;AAAA,MAC9E,GAAA,EAAK,SAAA;AAAA,MACL,YAAA,EAAc,IAAA;AAAA,MACd,YAAA,EAAc,IAAA;AAAA,MACd,OAAA,EAAS,IAAA;AAAA,MACT,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,MAAA,OAAA;AAAA,MACA,IAAA,wBACE,MAAA,EAAA,EACC,QAAA,kBAAA,IAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,WAAA;AAAA,UACL,0BAAA,EAAyB,EAAA;AAAA,UACzB,IAAA,EAAK,SAAA;AAAA,UACL,SAAA,EAAW,EAAA;AAAA,YACT,2JAAA;AAAA,YACA;AAAA,WACF;AAAA,UACA,OAAO,EAAE,IAAA,EAAM,SAAS,CAAA,EAAG,GAAA,EAAK,SAAS,CAAA,EAAE;AAAA,UAE1C,QAAA,EAAA;AAAA,YAAA,OAAA;AAAA,4BACD,GAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAW,EAAA;AAAA;AAAA;AAAA;AAAA,kBAIT,uCAAA;AAAA,kBACA,QAAA,CAAS,SAAA,CAAU,UAAA,CAAW,KAAK,CAAA,IACjC,yCAAA;AAAA,kBACF,QAAA,CAAS,SAAA,CAAU,UAAA,CAAW,QAAQ,CAAA,IACpC,sCAAA;AAAA,kBACF,QAAA,CAAS,SAAA,CAAU,UAAA,CAAW,MAAM,CAAA,IAClC,uCAAA;AAAA,kBACF,QAAA,CAAS,SAAA,CAAU,UAAA,CAAW,OAAO,CAAA,IACnC;AAAA;AACJ;AAAA;AACF;AAAA;AAAA,OACF,EACF;AAAA,KAAA,EAEJ,CAAA;AAAA,EAEJ;AACF;AAEA,OAAA,CAAQ,WAAA,GAAc,SAAA","file":"chunk-CF5KRDN4.js","sourcesContent":["import {\n cloneElement,\n forwardRef,\n useCallback,\n useRef,\n useState,\n type ReactElement,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Portal } from \"../Portal\";\nimport { useFloatingPosition } from \"../../hooks/use-floating-position\";\nimport type { TooltipProps } from \"./Tooltip.types\";\n\nexport const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(\n function Tooltip(\n { children, content, placement = \"top\", delay = 200, offset = 8, className },\n _ref,\n ) {\n const [open, setOpen] = useState(false);\n const anchorRef = useRef<HTMLElement>(null);\n const floatingRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n\n const position = useFloatingPosition(anchorRef, floatingRef, {\n placement,\n offset,\n enabled: open,\n });\n\n const show = useCallback(() => {\n timeoutRef.current = setTimeout(() => setOpen(true), delay);\n }, [delay]);\n\n const hide = useCallback(() => {\n clearTimeout(timeoutRef.current);\n setOpen(false);\n }, []);\n\n const trigger = cloneElement(children as ReactElement<Record<string, unknown>>, {\n ref: anchorRef,\n onMouseEnter: show,\n onMouseLeave: hide,\n onFocus: show,\n onBlur: hide,\n });\n\n return (\n <>\n {trigger}\n {open && (\n <Portal>\n <div\n ref={floatingRef}\n data-react-fancy-tooltip=\"\"\n role=\"tooltip\"\n className={cn(\n \"fancy-fade-in pointer-events-none fixed z-50 max-w-xs rounded-lg bg-zinc-900 px-3 py-1.5 text-sm text-white shadow-lg dark:bg-zinc-700 dark:text-zinc-100\",\n className,\n )}\n style={{ left: position.x, top: position.y }}\n >\n {content}\n <div\n className={cn(\n // `bg-inherit`, not a colour of its own: a `className` that\n // restyles the bubble would otherwise leave a dark arrow\n // pointing out of a light one.\n \"absolute h-2 w-2 rotate-45 bg-inherit\",\n position.placement.startsWith(\"top\") &&\n \"bottom-[-4px] left-1/2 -translate-x-1/2\",\n position.placement.startsWith(\"bottom\") &&\n \"top-[-4px] left-1/2 -translate-x-1/2\",\n position.placement.startsWith(\"left\") &&\n \"right-[-4px] top-1/2 -translate-y-1/2\",\n position.placement.startsWith(\"right\") &&\n \"left-[-4px] top-1/2 -translate-y-1/2\",\n )}\n />\n </div>\n </Portal>\n )}\n </>\n );\n },\n);\n\nTooltip.displayName = \"Tooltip\";\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk6TZPM43Q_cjs = require('./chunk-6TZPM43Q.cjs');
|
|
4
|
+
var chunkX7H75WVP_cjs = require('./chunk-X7H75WVP.cjs');
|
|
4
5
|
var chunkRMJGF7MN_cjs = require('./chunk-RMJGF7MN.cjs');
|
|
5
6
|
var chunkQKFOJKVE_cjs = require('./chunk-QKFOJKVE.cjs');
|
|
6
7
|
var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
|
|
@@ -46,9 +47,31 @@ function PromptInput({
|
|
|
46
47
|
maxHeight = 280,
|
|
47
48
|
aboveInput,
|
|
48
49
|
className,
|
|
50
|
+
pasteThreshold,
|
|
51
|
+
pasteImages = false,
|
|
52
|
+
previewChars = 20,
|
|
53
|
+
renderPastePreview,
|
|
54
|
+
pasteClassNames,
|
|
55
|
+
attachButton = "label",
|
|
56
|
+
sendButton = "label",
|
|
57
|
+
usedTokens,
|
|
58
|
+
meter = "always",
|
|
59
|
+
meterShowAt = 0.75,
|
|
60
|
+
meterWarnAt = 0.9,
|
|
49
61
|
...rest
|
|
50
62
|
}) {
|
|
51
63
|
const [text, setText] = react.useState("");
|
|
64
|
+
const inline = pasteThreshold !== void 0 || pasteImages;
|
|
65
|
+
const editorRef = react.useRef(null);
|
|
66
|
+
const paste = chunk6TZPM43Q_cjs.useInlinePaste({
|
|
67
|
+
pasteThreshold,
|
|
68
|
+
pasteImages,
|
|
69
|
+
previewChars,
|
|
70
|
+
renderPastePreview,
|
|
71
|
+
classNames: pasteClassNames,
|
|
72
|
+
disabled: false,
|
|
73
|
+
editorRef
|
|
74
|
+
});
|
|
52
75
|
const [attachments, setAttachments] = react.useState([]);
|
|
53
76
|
const [picker, setPicker] = react.useState(null);
|
|
54
77
|
const taRef = react.useRef(null);
|
|
@@ -62,12 +85,14 @@ function PromptInput({
|
|
|
62
85
|
}, [platform]);
|
|
63
86
|
const modKey = modifierKeyLabel(platform ?? detected);
|
|
64
87
|
const resolvedPlaceholder = placeholder ?? `Ask anything. Type / for commands, @ for mentions. ${modKey}+Enter to send.`;
|
|
65
|
-
const
|
|
66
|
-
() => Math.ceil(text.length / Math.max(1, charsPerToken)),
|
|
67
|
-
[text, charsPerToken]
|
|
88
|
+
const draftTokens = react.useMemo(
|
|
89
|
+
() => Math.ceil((inline ? paste.expand(text) : text).length / Math.max(1, charsPerToken)),
|
|
90
|
+
[text, inline, paste, charsPerToken]
|
|
68
91
|
);
|
|
92
|
+
const tokens = (usedTokens ?? 0) + draftTokens;
|
|
69
93
|
const ratio = Math.min(1, tokens / budgetTokens);
|
|
70
|
-
const
|
|
94
|
+
const meterLevel = meter === "hidden" ? null : meter === "near-limit" ? ratio < meterShowAt ? null : ratio >= meterWarnAt ? "warn" : "muted" : ratio < 0.6 ? "ok" : ratio < 0.85 ? "caution" : "warn";
|
|
95
|
+
const meterColor = meterLevel === "ok" ? "#10b981" : meterLevel === "caution" ? "#f59e0b" : meterLevel === "warn" ? "#ef4444" : "#a1a1aa";
|
|
71
96
|
const filteredCmds = react.useMemo(
|
|
72
97
|
() => picker?.kind === "cmd" ? commands.filter(
|
|
73
98
|
(c) => c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase())
|
|
@@ -121,6 +146,10 @@ function PromptInput({
|
|
|
121
146
|
const next = before + insert + after;
|
|
122
147
|
setText(next);
|
|
123
148
|
setPicker(null);
|
|
149
|
+
if (inline) {
|
|
150
|
+
editorRef.current?.setValue(next, before.length + insert.length);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
124
153
|
requestAnimationFrame(() => {
|
|
125
154
|
const ta = taRef.current;
|
|
126
155
|
if (!ta) return;
|
|
@@ -131,7 +160,19 @@ function PromptInput({
|
|
|
131
160
|
};
|
|
132
161
|
const submit = () => {
|
|
133
162
|
if (!text.trim() && attachments.length === 0) return;
|
|
134
|
-
|
|
163
|
+
if (inline) {
|
|
164
|
+
const pastedImages = paste.imagesIn(text).map((image) => ({
|
|
165
|
+
id: image.id,
|
|
166
|
+
name: image.file.name,
|
|
167
|
+
bytes: image.file.size,
|
|
168
|
+
file: image.file,
|
|
169
|
+
type: image.file.type
|
|
170
|
+
}));
|
|
171
|
+
onSubmit(paste.expand(text), [...attachments, ...pastedImages]);
|
|
172
|
+
paste.clear();
|
|
173
|
+
} else {
|
|
174
|
+
onSubmit(text, attachments);
|
|
175
|
+
}
|
|
135
176
|
setText("");
|
|
136
177
|
setAttachments([]);
|
|
137
178
|
setPicker(null);
|
|
@@ -233,7 +274,34 @@ function PromptInput({
|
|
|
233
274
|
a.id
|
|
234
275
|
)) }),
|
|
235
276
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
236
|
-
/* @__PURE__ */ jsxRuntime.
|
|
277
|
+
inline ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
278
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
279
|
+
chunk6TZPM43Q_cjs.InlinePasteEditor,
|
|
280
|
+
{
|
|
281
|
+
ref: editorRef,
|
|
282
|
+
value: text,
|
|
283
|
+
known: paste.known,
|
|
284
|
+
onChange: (next, caret) => {
|
|
285
|
+
updateText(next, caret);
|
|
286
|
+
paste.prune(next);
|
|
287
|
+
},
|
|
288
|
+
onSubmit: submit,
|
|
289
|
+
submitKey: "mod-enter",
|
|
290
|
+
onKeyDown,
|
|
291
|
+
onPaste: paste.decidePaste,
|
|
292
|
+
onHostsChange: paste.onHostsChange,
|
|
293
|
+
placeholder: resolvedPlaceholder,
|
|
294
|
+
disabled: false,
|
|
295
|
+
maxHeight,
|
|
296
|
+
placeholderClassName: "left-3 top-2.5 text-[14px] leading-relaxed",
|
|
297
|
+
className: chunkZU5Q77OT_cjs.cn(
|
|
298
|
+
"block min-h-[5.5rem] px-3 py-2.5 text-[14px] leading-relaxed",
|
|
299
|
+
pasteClassNames?.input
|
|
300
|
+
)
|
|
301
|
+
}
|
|
302
|
+
),
|
|
303
|
+
paste.portals
|
|
304
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
237
305
|
"textarea",
|
|
238
306
|
{
|
|
239
307
|
ref: taRef,
|
|
@@ -302,15 +370,17 @@ function PromptInput({
|
|
|
302
370
|
] })
|
|
303
371
|
] }),
|
|
304
372
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-t border-zinc-200 bg-zinc-50/60 px-3 py-2 dark:border-zinc-800 dark:bg-zinc-900/40", children: [
|
|
305
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
373
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkX7H75WVP_cjs.Tooltip, { content: attachButton === "icon" ? "Attach files \u2014 or drop them here" : "Drop files here, or click", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
306
374
|
chunkRMJGF7MN_cjs.Button,
|
|
307
375
|
{
|
|
308
376
|
variant: "ghost",
|
|
309
377
|
size: "sm",
|
|
310
378
|
icon: "paperclip",
|
|
311
379
|
className: "shrink-0",
|
|
380
|
+
"data-react-fancy-prompt-input-attach": "",
|
|
381
|
+
"aria-label": attachButton === "icon" ? "Attach files" : void 0,
|
|
312
382
|
onClick: () => fileRef.current?.click(),
|
|
313
|
-
children: "attach"
|
|
383
|
+
children: attachButton === "icon" ? null : "attach"
|
|
314
384
|
}
|
|
315
385
|
) }),
|
|
316
386
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -326,22 +396,30 @@ function PromptInput({
|
|
|
326
396
|
}
|
|
327
397
|
}
|
|
328
398
|
),
|
|
329
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
399
|
+
meterLevel !== null && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
400
|
+
"div",
|
|
401
|
+
{
|
|
402
|
+
"data-react-fancy-prompt-input-meter": "",
|
|
403
|
+
"data-level": meterLevel,
|
|
404
|
+
className: "ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden",
|
|
405
|
+
children: [
|
|
406
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
407
|
+
"div",
|
|
408
|
+
{
|
|
409
|
+
className: "h-full rounded-full transition-all",
|
|
410
|
+
style: { width: `${ratio * 100}%`, backgroundColor: meterColor }
|
|
411
|
+
}
|
|
412
|
+
) }),
|
|
413
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-[11px]", style: { color: meterColor }, children: [
|
|
414
|
+
fmtTokens(tokens),
|
|
415
|
+
" / ",
|
|
416
|
+
fmtTokens(budgetTokens)
|
|
417
|
+
] })
|
|
418
|
+
]
|
|
419
|
+
}
|
|
420
|
+
),
|
|
343
421
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
|
|
344
|
-
showHint && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
422
|
+
showHint && sendButton !== "icon" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
345
423
|
"span",
|
|
346
424
|
{
|
|
347
425
|
className: "hidden text-[10px] text-zinc-500 sm:inline",
|
|
@@ -357,13 +435,25 @@ function PromptInput({
|
|
|
357
435
|
]
|
|
358
436
|
}
|
|
359
437
|
),
|
|
360
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
438
|
+
sendButton === "icon" ? /* @__PURE__ */ jsxRuntime.jsx(chunkX7H75WVP_cjs.Tooltip, { content: `Send \xB7 ${modKey}+Enter`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
439
|
+
chunkRMJGF7MN_cjs.Button,
|
|
440
|
+
{
|
|
441
|
+
color: "violet",
|
|
442
|
+
size: "sm",
|
|
443
|
+
icon: "arrow-up",
|
|
444
|
+
className: "shrink-0",
|
|
445
|
+
"data-react-fancy-prompt-input-send": "",
|
|
446
|
+
"aria-label": "Send",
|
|
447
|
+
onClick: submit
|
|
448
|
+
}
|
|
449
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
361
450
|
chunkRMJGF7MN_cjs.Button,
|
|
362
451
|
{
|
|
363
452
|
color: "violet",
|
|
364
453
|
size: "sm",
|
|
365
454
|
iconTrailing: "arrow-right",
|
|
366
455
|
className: "shrink-0",
|
|
456
|
+
"data-react-fancy-prompt-input-send": "",
|
|
367
457
|
onClick: submit,
|
|
368
458
|
children: "send"
|
|
369
459
|
}
|
|
@@ -388,5 +478,5 @@ exports.PromptInput = PromptInput;
|
|
|
388
478
|
exports.browserPlatformHints = browserPlatformHints;
|
|
389
479
|
exports.detectPlatform = detectPlatform;
|
|
390
480
|
exports.modifierKeyLabel = modifierKeyLabel;
|
|
391
|
-
//# sourceMappingURL=chunk-
|
|
392
|
-
//# sourceMappingURL=chunk-
|
|
481
|
+
//# sourceMappingURL=chunk-FJ2GMQLC.cjs.map
|
|
482
|
+
//# sourceMappingURL=chunk-FJ2GMQLC.cjs.map
|