npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cosmic-ai-input

v1.0.40

Published

A powerful AI conversation input component for React with TypeScript support

Readme

Cosmic AI Input

一个强大的 React AI 对话输入组件,支持 TypeScript。

安装

npm install cosmic-ai-input

pnpm install cosmic-ai-input

依赖

这个组件需要以下 peer dependencies:

  • React 18.2.0+
  • React-DOM 18.2.0+
  • classnames 2.5.1+

请确保你的项目中已经安装了这些依赖

样式导入

重要: 使用本组件时,必须手动导入样式文件,否则组件将没有样式。

使用方法

ES 模块环境

import React, { useRef } from "react";
import { AiInput } from "cosmic-ai-input";
// 导入样式(推荐方法)
import "cosmic-ai-input/dist/style.css";

const App = () => {
  const aiInputRef = useRef(null);

  const varList = [
    {
      type: "input",
      name: "name",
      content: "",
      placeholder: "Your name",
    },
    {
      type: "select",
      name: "gender",
      content: "",
      placeholder: "Select gender",
      options: ["Male", "Female", "Other"],
    },
    {
      type: "multiple-select",
      name: "hobbies",
      content: "",
      placeholder: "Select hobbies",
      options: ["Reading", "Sports", "Music", "Travel"],
    },
    {
      type: "date-picker",
      name: "birthday",
      content: "",
      placeholder: "Select birthday",
    },
    {
      type: "label",
      name: "tags",
      content: "",
    },
  ];

  const mentions = [
    {
      prefix: "@",
      options: ["User1", "User2", "User3"],
    },
    {
      prefix: "[",
      options: ["name", "gender", "hobbies", "birthday", "tags"],
    },
  ];

  const handleSend = (value) => {
    console.log("发送的消息:", value);
    // 在这里处理发送逻辑
  };

  const handleGetValue = () => {
    if (aiInputRef.current) {
      const currentValue = aiInputRef.current.getCurrentValue();
      console.log("当前值:", currentValue);
    }
  };

  const handleFocus = () => {
    if (aiInputRef.current) {
      aiInputRef.current.focus();
    }
  };

  return (
    <div>
      <h1>AI 对话输入组件示例</h1>
      <AiInput
        ref={aiInputRef}
        varList={varList}
        mentions={mentions}
        value="你好 [name],你的性别是 [gender],爱好是 [hobbies],生日是 [birthday]"
        placeholder="在这里输入你的消息..."
        onSend={handleSend}
      />
      <button onClick={handleGetValue}>获取当前值</button>
      <button onClick={handleFocus}>获得焦点</button>
    </div>
  );
};

export default App;

键盘快捷键

| 快捷键 | 行为(enterMode="send") | 行为(enterMode="newline") | | ---------------- | ------------------------ | --------------------------- | | Enter | 发送消息 | 换行 | | Shift + Enter | 换行 | 发送消息 | | Ctrl/Cmd + Enter | - | 发送消息 | | 上下箭头 | 在提及选项列表中导航 | 在提及选项列表中导航 | | Escape | 关闭打开的下拉菜单 | 关闭打开的下拉菜单 |

API

AiInputProps

| 属性 | 类型 | 默认值 | 描述 | | ------------------- | ------------------------------------------ | -------- | -------------------------------------------------------------------------------------------------- | | value | string | - | 输入框的值,支持使用 [变量名] 格式引用变量 | | varList | VarItem[] | - | 变量列表,包含输入框、选择框、多选框、日期选择器和标签等 | | placeholder | string | '' | 占位符文本 | | maxLength | 1 | 2 | 3 | 4 | undefined | - | 最大行数限制 | | defaultRows | number | 3 | 默认显示行数 | | disabled | boolean | false | 是否禁用输入框 | | defaultFocus | boolean | false | 是否默认获得焦点 | | textIndex | number | 0 | 文本缩进距离(单位:像素) | | mentions | MentionItem[] | [] | 提及配置,支持自定义前缀触发选项列表 | | enterMode | 'send' | 'newline' | 'send' | 回车键行为模式。send:Enter 发送,Shift+Enter 换行;newline:Enter 换行,Shift/Ctrl/Cmd+Enter 发送 | | mentionPlacement | 'cursor' | 'bottom' | 'cursor' | 提及浮窗定位模式。cursor:出现在光标位置旁;bottom:出现在输入框下方,宽度与输入框一致 | | mentionMaxHeight | number | 240 | 提及浮窗的最大高度(px)。内容不足时按内容收缩,超出则浮窗内部滚动 | | onMentionSelect | (payload: MentionSelectPayload) => void | - | 选中并插入某个提及项时触发,可拿到插入的值和完整选项对象 | | onMentionDelete | (payload: MentionDeletePayload) => void | - | 在输入框中删除某个已插入的提及标签时触发 | | onParse | (parsedValue: string) => void | - | 解析输入值时的回调函数 | | onSend | (value: string) => void | - | 发送消息时的回调函数(按 Enter 键触发) | | onMaxLengthExceeded | (value: string, maxLength: number) => void | - | 超过最大长度时的回调函数 | | onFocus | (e: React.FocusEvent) => void | - | 获得焦点时的回调函数 | | onBlur | (e: React.FocusEvent) => void | - | 失去焦点时的回调函数 | | onChange | (value: string) => void | - | 值改变时的回调函数 | | onClick | (e: React.MouseEvent) => void | - | 点击时的回调函数 | | onKeyDown | (e: React.KeyboardEvent) => void | - | 按键按下时的回调函数 | | onKeyUp | (e: React.KeyboardEvent) => void | - | 按键抬起时的回调函数 |

BaseInputItem

所有输入项的基础接口:

| 属性 | 类型 | 描述 | | ----------- | ------ | --------------------------- | | type | string | 组件类型 | | name | string | 变量名,用于在 value 中引用 | | content | string | 初始内容 | | placeholder | string | 占位符文本 |

InputItem

基础输入项:

interface InputItem extends BaseInputItem {
  type: "input";
}

SelectItem

下拉选择项:

interface SelectItem extends BaseInputItem {
  type: "select";
  options: string[]; // 选项列表
}

MultipleSelectItem

多选框项:

interface MultipleSelectItem extends BaseInputItem {
  type: "multiple-select";
  options: string[]; // 选项列表
}

DatePickerItem

日期选择器项:

interface DatePickerItem extends BaseInputItem {
  type: "date-picker";
}

LabelItem

标签项:

interface LabelItem {
  type: "label"; // 类型为 label
  name: string; // 变量名,用于在 value 中引用
  content: string; // 标签内容
}

MentionItem

提及配置项:

interface MentionOption {
  label: string; // 显示标题,也是默认插入到输入框的值
  value?: string; // 可选,标签上展示的文本,默认使用 label
  insertText?: string; // 可选,真正序列化进输入框 value 的文本,默认使用 value。可实现「标签显示一种、实际插入另一种」
  description?: string; // 描述文本(标题下方小字)
  icon?: React.ReactNode; // 图标,可传图片 URL 字符串或 ReactNode
}

interface MentionItem {
  prefix: string; // 触发前缀,如 '@' 或 '['
  title?: string; // 下拉框顶部标题
  searchable?: boolean; // 是否显示搜索框,默认 false
  searchPlaceholder?: string; // 搜索框占位符,默认 '搜索'
  options: (string | MentionOption)[]; // 选项列表,支持纯字符串或富对象
}

// onMentionSelect 回调载荷
interface MentionSelectPayload {
  prefix: string; // 触发的前缀
  value: string; // 实际插入到输入框的值
  option: MentionOption; // 命中的完整选项对象
  id: string; // 该标签在 DOM 中的唯一 id
}

// onMentionDelete 回调载荷
interface MentionDeletePayload {
  prefix: string; // 触发的前缀
  value: string; // 被删除标签的文本
  option: MentionOption; // 命中的完整选项对象
  id: string; // 被删除标签的 id
}

简单用法(纯文本选项):

<AiInput
  mentions={[
    {
      prefix: '@',
      options: ['用户1', '用户2', '用户3']
    },
    {
      prefix: '[',
      options: ['话题1', '话题2', '话题3']
    }
  ]}
  // 当用户输入 @ 或 [ 时,会显示对应的选项列表
  // 支持键盘上下箭头导航,回车选择
/>

富选项用法(带图标、描述、搜索框):

<AiInput
  mentions={[
    {
      prefix: '@',
      title: '选择智能体',
      searchable: true,
      searchPlaceholder: '搜索智能体',
      options: [
        {
          label: '嵌入式AI分析助手',
          description: '过滤单据、生成图表助手',
          icon: 'https://example.com/icon1.png'
        },
        {
          label: '客户销售订单分析助手',
          description: '输入客户名称,自动查询销售订单',
          icon: <MyIconComponent />
        }
      ]
    }
  ]}
/>

自定义插入文本 & 回显(insertText):

insertText 让「标签上展示的文本」和「真正插入到 value 的文本」解耦,并作为回显时的识别标记:

<AiInput
  value={value}            // 把之前保存的纯文本传回来即可回显
  onChange={setValue}
  mentions={[
    {
      prefix: '@',
      options: [
        {
          label: '嵌入式AI分析助手',          // 下拉里展示
          insertText: '{{agent:embedded-ai}}', // 标签显示「嵌入式AI分析助手」,但 value 里序列化成这段
        },
      ],
    },
  ]}
/>
  • 选中后标签显示 label(或 value),但 getCurrentValue() / onChange 输出的纯文本里这段是 insertText
  • 回显:把保存的纯文本通过 value 传回来,组件会扫描其中命中任一 option insertText 的片段,自动还原成高亮标签。
  • 回显能力仅对显式设置了 insertText 的 option 生效。建议 insertText 用独特、不会和正常文本撞的 token(如 {{agent:xxx}}),否则可能把用户手打的普通文字误识别成标签。
  • 多个 token 存在子串包含关系时按最长优先匹配;同一 token 出现多次会各自还原。

AiInputRef

通过 ref 可以访问的方法:

| 方法 | 类型 | 描述 | | --------------- | ------------ | ---------------------------------------------- | | getCurrentValue | () => string | 获取当前输入框的值(包含变量替换后的完整文本) | | focus | () => void | 让输入框获得焦点 |

TypeScript 支持

本组件完全支持 TypeScript,并提供了完整的类型定义。所有组件属性和方法都有类型检查,可以在开发过程中获得更好的代码提示和错误检测。

类型定义

import React from "react";

export interface BaseInputItem {
  name: string;
  content: string;
  placeholder: string;
}

export interface InputItem extends BaseInputItem {
  type: "input";
}

export interface SelectItem extends BaseInputItem {
  type: "select";
  options: string[];
}

export interface MultipleSelectItem extends BaseInputItem {
  type: "multiple-select";
  options: string[];
}

export interface DatePickerItem extends BaseInputItem {
  type: "date-picker";
}

export interface LabelItem {
  type: "label";
  name: string;
  content: string;
}

export interface MentionOption {
  label: string;
  value?: string;
  insertText?: string;
  description?: string;
  icon?: React.ReactNode;
}

export interface MentionItem {
  prefix: string;
  title?: string;
  searchable?: boolean;
  searchPlaceholder?: string;
  options: (string | MentionOption)[];
}

export interface MentionSelectPayload {
  prefix: string;
  value: string;
  option: MentionOption;
  id: string;
}

export interface MentionDeletePayload {
  prefix: string;
  value: string;
  option: MentionOption;
  id: string;
}

export type VarItem =
  | InputItem
  | SelectItem
  | MultipleSelectItem
  | DatePickerItem
  | LabelItem;

export interface AiInputProps {
  value?: string;
  varList: VarItem[];
  placeholder?: string;
  maxLength?: 1 | 2 | 3 | 4;
  defaultRows?: number;
  disabled?: boolean;
  defaultFocus?: boolean;
  textIndex?: number;
  mentions?: MentionItem[];
  enterMode?: "send" | "newline";
  mentionPlacement?: "cursor" | "bottom";
  mentionMaxHeight?: number;
  onMentionSelect?: (payload: MentionSelectPayload) => void;
  onMentionDelete?: (payload: MentionDeletePayload) => void;
  onParse?: (parsedValue: string) => void;
  onSend?: (value: string) => void;
  onMaxLengthExceeded?: (value: string, maxLength: number) => void;
  onFocus?: (e: React.FocusEvent) => void;
  onBlur?: (e: React.FocusEvent) => void;
  onChange?: (value: string) => void;
  onClick?: (e: React.MouseEvent) => void;
  onKeyDown?: (e: React.KeyboardEvent) => void;
  onKeyUp?: (e: React.KeyboardEvent) => void;
}

export interface AiInputRef {
  getCurrentValue: () => string;
  focus: () => void;
}