@particle-academy/react-fancy 5.26.0 → 5.27.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.
@@ -150,6 +150,13 @@ function PromptInput({
150
150
  setDragOver(false);
151
151
  attach(e.dataTransfer.files);
152
152
  };
153
+ const onPaste = (e) => {
154
+ const data = e.clipboardData;
155
+ const files = Array.from(data?.files ?? []);
156
+ if (files.length === 0 || (data?.getData("text/plain") ?? "") !== "") return;
157
+ e.preventDefault();
158
+ attach(files);
159
+ };
153
160
  return /* @__PURE__ */ jsxs(
154
161
  "div",
155
162
  {
@@ -191,6 +198,7 @@ function PromptInput({
191
198
  value: text,
192
199
  onChange: (e) => updateText(e.target.value, e.target.selectionStart),
193
200
  onKeyDown,
201
+ onPaste,
194
202
  placeholder,
195
203
  spellCheck: false,
196
204
  className: "block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400",
@@ -317,5 +325,5 @@ function fmtSize(b) {
317
325
  }
318
326
 
319
327
  export { PromptInput };
320
- //# sourceMappingURL=chunk-3LM47BME.js.map
321
- //# sourceMappingURL=chunk-3LM47BME.js.map
328
+ //# sourceMappingURL=chunk-BYKTW7J5.js.map
329
+ //# sourceMappingURL=chunk-BYKTW7J5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/PromptInput/PromptInput.tsx"],"names":[],"mappings":"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","file":"chunk-BYKTW7J5.js","sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Button } from \"../Button\";\nimport { Tooltip } from \"../Tooltip\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface), paste-to-attach\n * (a pasted screenshot becomes an attachment) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\nexport interface PromptInputProps {\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"⌘ + Enter to send\"). */\n showHint?: boolean;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /** Placeholder text. */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n onSubmit,\n placeholder = \"Ask anything. Type / for commands, @ for mentions. ⌘/Ctrl+Enter to send.\",\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n const tokens = useMemo(\n () => Math.ceil(text.length / Math.max(1, charsPerToken)),\n [text, charsPerToken],\n );\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterColor = ratio < 0.6 ? \"#10b981\" : ratio < 0.85 ? \"#f59e0b\" : \"#ef4444\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n if (!text.trim() && attachments.length === 0) return;\n onSubmit(text, attachments);\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n if (e.key === \"Enter\" && !e.metaKey && !e.ctrlKey && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n /**\n * Paste a screenshot, get an attachment.\n *\n * There was no paste handler at all, so a pasted image did nothing — no chip,\n * no error — and a host that had swapped its own paste-capable textarea for\n * this component lost the feature without noticing.\n *\n * Files attach only when the clipboard carries NO plain text. Word, Excel and\n * most editors put a picture of the selection beside the text; attaching that\n * would turn every pasted sentence into a screenshot of the sentence. A pure\n * image paste has nothing for the browser to insert, so the default is\n * prevented only then, and a text paste is never touched.\n */\n const onPaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const data = e.clipboardData;\n const files = Array.from(data?.files ?? []);\n\n if (files.length === 0 || (data?.getData(\"text/plain\") ?? \"\") !== \"\") return;\n\n e.preventDefault();\n attach(files);\n };\n\n return (\n <div\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={`relative rounded-md border transition ${\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\"\n } bg-white dark:bg-zinc-900`}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <span>📎</span>\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <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\">\n <Tooltip content=\"Drop files here, or click\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"shrink-0\"\n onClick={() => fileRef.current?.click()}\n >\n 📎 attach\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n <div className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\">\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {showHint && (\n <span className=\"hidden text-[10px] text-zinc-500 sm:inline\">\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n ⌘\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n <Button color=\"violet\" size=\"sm\" className=\"shrink-0\" onClick={submit}>\n send →\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}
@@ -152,6 +152,13 @@ function PromptInput({
152
152
  setDragOver(false);
153
153
  attach(e.dataTransfer.files);
154
154
  };
155
+ const onPaste = (e) => {
156
+ const data = e.clipboardData;
157
+ const files = Array.from(data?.files ?? []);
158
+ if (files.length === 0 || (data?.getData("text/plain") ?? "") !== "") return;
159
+ e.preventDefault();
160
+ attach(files);
161
+ };
155
162
  return /* @__PURE__ */ jsxRuntime.jsxs(
156
163
  "div",
157
164
  {
@@ -193,6 +200,7 @@ function PromptInput({
193
200
  value: text,
194
201
  onChange: (e) => updateText(e.target.value, e.target.selectionStart),
195
202
  onKeyDown,
203
+ onPaste,
196
204
  placeholder,
197
205
  spellCheck: false,
198
206
  className: "block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400",
@@ -319,5 +327,5 @@ function fmtSize(b) {
319
327
  }
320
328
 
321
329
  exports.PromptInput = PromptInput;
322
- //# sourceMappingURL=chunk-SO4NNG26.cjs.map
323
- //# sourceMappingURL=chunk-SO4NNG26.cjs.map
330
+ //# sourceMappingURL=chunk-RHDBBXHO.cjs.map
331
+ //# sourceMappingURL=chunk-RHDBBXHO.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/PromptInput/PromptInput.tsx"],"names":["useState","useRef","useMemo","useEffect","jsxs","jsx","Tooltip","Button"],"mappings":"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","file":"chunk-RHDBBXHO.cjs","sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Button } from \"../Button\";\nimport { Tooltip } from \"../Tooltip\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface), paste-to-attach\n * (a pasted screenshot becomes an attachment) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\nexport interface PromptInputProps {\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"⌘ + Enter to send\"). */\n showHint?: boolean;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /** Placeholder text. */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n onSubmit,\n placeholder = \"Ask anything. Type / for commands, @ for mentions. ⌘/Ctrl+Enter to send.\",\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n const tokens = useMemo(\n () => Math.ceil(text.length / Math.max(1, charsPerToken)),\n [text, charsPerToken],\n );\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterColor = ratio < 0.6 ? \"#10b981\" : ratio < 0.85 ? \"#f59e0b\" : \"#ef4444\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n if (!text.trim() && attachments.length === 0) return;\n onSubmit(text, attachments);\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n if (e.key === \"Enter\" && !e.metaKey && !e.ctrlKey && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n /**\n * Paste a screenshot, get an attachment.\n *\n * There was no paste handler at all, so a pasted image did nothing — no chip,\n * no error — and a host that had swapped its own paste-capable textarea for\n * this component lost the feature without noticing.\n *\n * Files attach only when the clipboard carries NO plain text. Word, Excel and\n * most editors put a picture of the selection beside the text; attaching that\n * would turn every pasted sentence into a screenshot of the sentence. A pure\n * image paste has nothing for the browser to insert, so the default is\n * prevented only then, and a text paste is never touched.\n */\n const onPaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const data = e.clipboardData;\n const files = Array.from(data?.files ?? []);\n\n if (files.length === 0 || (data?.getData(\"text/plain\") ?? \"\") !== \"\") return;\n\n e.preventDefault();\n attach(files);\n };\n\n return (\n <div\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={`relative rounded-md border transition ${\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\"\n } bg-white dark:bg-zinc-900`}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <span>📎</span>\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={placeholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <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\">\n <Tooltip content=\"Drop files here, or click\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"shrink-0\"\n onClick={() => fileRef.current?.click()}\n >\n 📎 attach\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n <div className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\">\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {showHint && (\n <span className=\"hidden text-[10px] text-zinc-500 sm:inline\">\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n ⌘\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n <Button color=\"violet\" size=\"sm\" className=\"shrink-0\" onClick={submit}>\n send →\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}
package/dist/index.cjs CHANGED
@@ -27,7 +27,7 @@ var chunk3EIB7RPD_cjs = require('./chunk-3EIB7RPD.cjs');
27
27
  require('./chunk-XURQVDCN.cjs');
28
28
  var chunkPFEFKLUV_cjs = require('./chunk-PFEFKLUV.cjs');
29
29
  var chunk6QVJY3RM_cjs = require('./chunk-6QVJY3RM.cjs');
30
- var chunkSO4NNG26_cjs = require('./chunk-SO4NNG26.cjs');
30
+ var chunkRHDBBXHO_cjs = require('./chunk-RHDBBXHO.cjs');
31
31
  var chunkISPCXIJZ_cjs = require('./chunk-ISPCXIJZ.cjs');
32
32
  var chunkWKAEAGMT_cjs = require('./chunk-WKAEAGMT.cjs');
33
33
  var chunkICT477LK_cjs = require('./chunk-ICT477LK.cjs');
@@ -226,7 +226,7 @@ Object.defineProperty(exports, "Progress", {
226
226
  });
227
227
  Object.defineProperty(exports, "PromptInput", {
228
228
  enumerable: true,
229
- get: function () { return chunkSO4NNG26_cjs.PromptInput; }
229
+ get: function () { return chunkRHDBBXHO_cjs.PromptInput; }
230
230
  });
231
231
  Object.defineProperty(exports, "Tooltip", {
232
232
  enumerable: true,
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ export { Tabs, useTabs } from './chunk-VME5743O.js';
25
25
  import './chunk-TMR56BBE.js';
26
26
  export { Profile } from './chunk-KQQA7JBC.js';
27
27
  export { Progress } from './chunk-YM6F2JIT.js';
28
- export { PromptInput } from './chunk-3LM47BME.js';
28
+ export { PromptInput } from './chunk-BYKTW7J5.js';
29
29
  export { Tooltip } from './chunk-35EN5AYE.js';
30
30
  export { PullQuote } from './chunk-NDUEPDNS.js';
31
31
  export { ReasonTag } from './chunk-SAF5642F.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkSO4NNG26_cjs = require('./chunk-SO4NNG26.cjs');
3
+ var chunkRHDBBXHO_cjs = require('./chunk-RHDBBXHO.cjs');
4
4
  require('./chunk-ISPCXIJZ.cjs');
5
5
  require('./chunk-M5MUGSON.cjs');
6
6
  require('./chunk-F2VJEXN2.cjs');
@@ -15,7 +15,7 @@ require('./chunk-ZU5Q77OT.cjs');
15
15
 
16
16
  Object.defineProperty(exports, "PromptInput", {
17
17
  enumerable: true,
18
- get: function () { return chunkSO4NNG26_cjs.PromptInput; }
18
+ get: function () { return chunkRHDBBXHO_cjs.PromptInput; }
19
19
  });
20
20
  //# sourceMappingURL=prompt-input.cjs.map
21
21
  //# sourceMappingURL=prompt-input.cjs.map
@@ -8,7 +8,8 @@ import { ReactNode } from 'react';
8
8
  * • slash-command picker (`/` triggers a filtered command palette,
9
9
  * ↑/↓ navigate, Enter inserts)
10
10
  * • mention picker (`@` triggers, filtered against `mentions`)
11
- * • drop-to-attach (drag files anywhere on the surface) + chip bar
11
+ * • drop-to-attach (drag files anywhere on the surface), paste-to-attach
12
+ * (a pasted screenshot becomes an attachment) + chip bar
12
13
  * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)
13
14
  * • live token-budget meter (green → amber → red as headroom drops)
14
15
  *
@@ -8,7 +8,8 @@ import { ReactNode } from 'react';
8
8
  * • slash-command picker (`/` triggers a filtered command palette,
9
9
  * ↑/↓ navigate, Enter inserts)
10
10
  * • mention picker (`@` triggers, filtered against `mentions`)
11
- * • drop-to-attach (drag files anywhere on the surface) + chip bar
11
+ * • drop-to-attach (drag files anywhere on the surface), paste-to-attach
12
+ * (a pasted screenshot becomes an attachment) + chip bar
12
13
  * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)
13
14
  * • live token-budget meter (green → amber → red as headroom drops)
14
15
  *
@@ -1,4 +1,4 @@
1
- export { PromptInput } from './chunk-3LM47BME.js';
1
+ export { PromptInput } from './chunk-BYKTW7J5.js';
2
2
  import './chunk-35EN5AYE.js';
3
3
  import './chunk-LQ4ICCN2.js';
4
4
  import './chunk-VYQI4R6S.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.26.0",
3
+ "version": "5.27.0",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",
@@ -969,7 +969,7 @@
969
969
  "tsup": "^8.0.0",
970
970
  "typescript": "^5.7.0",
971
971
  "typescript-eslint": "^8.65.0",
972
- "vitest": "^3.2.7"
972
+ "vitest": "^4.1.11"
973
973
  },
974
974
  "publishConfig": {
975
975
  "access": "public"
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/PromptInput/PromptInput.tsx"],"names":[],"mappings":"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","file":"chunk-3LM47BME.js","sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Button } from \"../Button\";\nimport { Tooltip } from \"../Tooltip\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\nexport interface PromptInputProps {\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"⌘ + Enter to send\"). */\n showHint?: boolean;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /** Placeholder text. */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n onSubmit,\n placeholder = \"Ask anything. Type / for commands, @ for mentions. ⌘/Ctrl+Enter to send.\",\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n const tokens = useMemo(\n () => Math.ceil(text.length / Math.max(1, charsPerToken)),\n [text, charsPerToken],\n );\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterColor = ratio < 0.6 ? \"#10b981\" : ratio < 0.85 ? \"#f59e0b\" : \"#ef4444\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n if (!text.trim() && attachments.length === 0) return;\n onSubmit(text, attachments);\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n if (e.key === \"Enter\" && !e.metaKey && !e.ctrlKey && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n return (\n <div\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={`relative rounded-md border transition ${\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\"\n } bg-white dark:bg-zinc-900`}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <span>📎</span>\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <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\">\n <Tooltip content=\"Drop files here, or click\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"shrink-0\"\n onClick={() => fileRef.current?.click()}\n >\n 📎 attach\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n <div className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\">\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {showHint && (\n <span className=\"hidden text-[10px] text-zinc-500 sm:inline\">\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n ⌘\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n <Button color=\"violet\" size=\"sm\" className=\"shrink-0\" onClick={submit}>\n send →\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/PromptInput/PromptInput.tsx"],"names":["useState","useRef","useMemo","useEffect","jsxs","jsx","Tooltip","Button"],"mappings":"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","file":"chunk-SO4NNG26.cjs","sourcesContent":["import { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { Button } from \"../Button\";\nimport { Tooltip } from \"../Tooltip\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\nexport interface PromptInputProps {\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"⌘ + Enter to send\"). */\n showHint?: boolean;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /** Placeholder text. */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n onSubmit,\n placeholder = \"Ask anything. Type / for commands, @ for mentions. ⌘/Ctrl+Enter to send.\",\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n const tokens = useMemo(\n () => Math.ceil(text.length / Math.max(1, charsPerToken)),\n [text, charsPerToken],\n );\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterColor = ratio < 0.6 ? \"#10b981\" : ratio < 0.85 ? \"#f59e0b\" : \"#ef4444\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n if (!text.trim() && attachments.length === 0) return;\n onSubmit(text, attachments);\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n if (e.key === \"Enter\" && !e.metaKey && !e.ctrlKey && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n return (\n <div\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={`relative rounded-md border transition ${\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\"\n } bg-white dark:bg-zinc-900`}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <span>📎</span>\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <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\">\n <Tooltip content=\"Drop files here, or click\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"shrink-0\"\n onClick={() => fileRef.current?.click()}\n >\n 📎 attach\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n <div className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\">\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {showHint && (\n <span className=\"hidden text-[10px] text-zinc-500 sm:inline\">\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n ⌘\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n <Button color=\"violet\" size=\"sm\" className=\"shrink-0\" onClick={submit}>\n send →\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}