cosmic-ai-input 1.0.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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ ISC License
2
+
3
+ Copyright (c) [year], [fullname]
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,299 @@
1
+ # Cosmic AI Input
2
+
3
+ 一个强大的 React AI 对话输入组件,支持 TypeScript。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install cosmic-ai-input
9
+ pnpm install cosmic-ai-input
10
+ ```
11
+
12
+ ## 依赖
13
+
14
+ 这个组件需要以下 peer dependencies:
15
+
16
+ - React 18.2.0+
17
+ - React-DOM 18.2.0+
18
+ - classnames 2.5.1+
19
+
20
+ 请确保你的项目中已经安装了这些依赖
21
+
22
+ ## 样式导入
23
+
24
+ **重要:** 使用本组件时,必须手动导入样式文件,否则组件将没有样式。
25
+
26
+ ```css
27
+ /* 在你的全局 CSS 文件中导入 */
28
+ @import 'cosmic-ai-input/dist/style.css';
29
+ ```
30
+
31
+ ## 使用方法
32
+
33
+ ### ES 模块环境
34
+
35
+ ```jsx
36
+ import React, { useRef } from 'react';
37
+ import { AiInput } from 'cosmic-ai-input';
38
+ // 导入样式(推荐方法)
39
+ import 'cosmic-ai-input/styles.css';
40
+
41
+ const App = () => {
42
+ const aiInputRef = useRef(null);
43
+
44
+ const varList = [
45
+ {
46
+ type: 'input',
47
+ name: 'name',
48
+ content: '',
49
+ cosmic-ai-input-placeholder: 'Your name'
50
+ },
51
+ {
52
+ type: 'select',
53
+ name: 'gender',
54
+ content: '',
55
+ cosmic-ai-input-placeholder: 'Select gender',
56
+ options: ['Male', 'Female', 'Other']
57
+ },
58
+ {
59
+ type: 'multiple-select',
60
+ name: 'hobbies',
61
+ content: '',
62
+ cosmic-ai-input-placeholder: 'Select hobbies',
63
+ options: ['Reading', 'Sports', 'Music', 'Travel']
64
+ },
65
+ {
66
+ type: 'date-picker',
67
+ name: 'birthday',
68
+ content: '',
69
+ cosmic-ai-input-placeholder: 'Select birthday'
70
+ }
71
+ ];
72
+
73
+ const handleSend = (value) => {
74
+ console.log('发送的消息:', value);
75
+ // 在这里处理发送逻辑
76
+ };
77
+
78
+ const handleGetValue = () => {
79
+ if (aiInputRef.current) {
80
+ const currentValue = aiInputRef.current.getCurrentValue();
81
+ console.log('当前值:', currentValue);
82
+ }
83
+ };
84
+
85
+ return (
86
+ <div>
87
+ <h1>AI 对话输入组件示例</h1>
88
+ <AiInput
89
+ ref={aiInputRef}
90
+ varList={varList}
91
+ value="你好 [name],你的性别是 [gender],爱好是 [hobbies],生日是 [birthday]"
92
+ cosmic-ai-input-placeholder="在这里输入你的消息..."
93
+ onSend={handleSend}
94
+ />
95
+ <button onClick={handleGetValue}>获取当前值</button>
96
+ </div>
97
+ );
98
+ };
99
+
100
+ export default App;
101
+ ```
102
+
103
+ ### CommonJS 环境
104
+
105
+ ```jsx
106
+ const React = require('react');
107
+ const { useRef } = React;
108
+ const { AiInput } = require('cosmic-ai-input');
109
+ // 获取样式文件路径
110
+ const styles = require('cosmic-ai-input/styles.cjs');
111
+
112
+ const App = () => {
113
+ const aiInputRef = useRef(null);
114
+
115
+ const varList = [
116
+ {
117
+ type: 'input',
118
+ name: 'name',
119
+ content: '',
120
+ cosmic-ai-input-placeholder: 'Your name'
121
+ },
122
+ {
123
+ type: 'select',
124
+ name: 'gender',
125
+ content: '',
126
+ cosmic-ai-input-placeholder: 'Select gender',
127
+ options: ['Male', 'Female', 'Other']
128
+ },
129
+ {
130
+ type: 'multiple-select',
131
+ name: 'hobbies',
132
+ content: '',
133
+ cosmic-ai-input-placeholder: 'Select hobbies',
134
+ options: ['Reading', 'Sports', 'Music', 'Travel']
135
+ },
136
+ {
137
+ type: 'date-picker',
138
+ name: 'birthday',
139
+ content: '',
140
+ cosmic-ai-input-placeholder: 'Select birthday'
141
+ }
142
+ ];
143
+
144
+ const handleSend = (value) => {
145
+ console.log('发送的消息:', value);
146
+ // 在这里处理发送逻辑
147
+ };
148
+
149
+ const handleGetValue = () => {
150
+ if (aiInputRef.current) {
151
+ const currentValue = aiInputRef.current.getCurrentValue();
152
+ console.log('当前值:', currentValue);
153
+ }
154
+ };
155
+
156
+ return (
157
+ <div>
158
+ {/* 在 HTML 中手动引入样式文件 */}
159
+ <link rel="stylesheet" href={styles.stylePath} />
160
+
161
+ <h1>AI 对话输入组件示例</h1>
162
+ <AiInput
163
+ ref={aiInputRef}
164
+ varList={varList}
165
+ value="你好 [name],你的性别是 [gender],爱好是 [hobbies],生日是 [birthday]"
166
+ cosmic-ai-input-placeholder="在这里输入你的消息..."
167
+ onSend={handleSend}
168
+ />
169
+ <button onClick={handleGetValue}>获取当前值</button>
170
+ </div>
171
+ );
172
+ };
173
+
174
+ module.exports = App;
175
+ ```
176
+
177
+ ## API
178
+
179
+ ### AiInputProps
180
+
181
+ | 属性 | 类型 | 默认值 | 描述 |
182
+ |------|------|--------|------|
183
+ | value | string | - | 输入框的值 |
184
+ | varList | InputItem[] | - | 变量列表 |
185
+ | cosmic-ai-input-placeholder | string | '' | 占位符文本 |
186
+ | maxLength | 1 \| 2 \| 3 \| 4 \| undefined | - | 最大行数 |
187
+ | defaultRows | number | 3 | 默认行数 |
188
+ | disabled | boolean | false | 是否禁用 |
189
+ | onParse | (parsedValue: string) => void | - | 解析输入值时的回调 |
190
+ | onSend | (value: string) => void | - | 发送消息时的回调 |
191
+ | onMaxLengthExceeded | (value: string, maxLength: number) => void | - | 超过最大长度时的回调 |
192
+ | onFocus | (e: React.FocusEvent) => void | - | 获得焦点时的回调 |
193
+ | onBlur | (e: React.FocusEvent) => void | - | 失去焦点时的回调 |
194
+ | onChange | (value: string) => void | - | 值改变时的回调 |
195
+ | onClick | (e: React.MouseEvent) => void | - | 点击时的回调 |
196
+ | onKeyDown | (e: React.KeyboardEvent) => void | - | 按键按下时的回调 |
197
+ | onKeyUp | (e: React.KeyboardEvent) => void | - | 按键抬起时的回调 |
198
+
199
+ ### InputItem
200
+
201
+ | 属性 | 类型 | 描述 |
202
+ |------|------|------|
203
+ | type | 'input' | 组件类型 |
204
+ | name | string | 变量名 |
205
+ | content | string | 内容 |
206
+ | cosmic-ai-input-placeholder | string | 占位符文本 |
207
+
208
+ ### SelectItem
209
+
210
+ | 属性 | 类型 | 描述 |
211
+ |------|------|------|
212
+ | type | 'select' | 组件类型 |
213
+ | name | string | 变量名 |
214
+ | content | string | 内容 |
215
+ | cosmic-ai-input-placeholder | string | 占位符文本 |
216
+ | options | string[] | 选项列表 |
217
+
218
+ ### MultipleSelectItem
219
+
220
+ | 属性 | 类型 | 描述 |
221
+ |------|------|------|
222
+ | type | 'multiple-select' | 组件类型 |
223
+ | name | string | 变量名 |
224
+ | content | string | 内容 |
225
+ | cosmic-ai-input-placeholder | string | 占位符文本 |
226
+ | options | string[] | 选项列表 |
227
+
228
+ ### DatePickerItem
229
+
230
+ | 属性 | 类型 | 描述 |
231
+ |------|------|------|
232
+ | type | 'date-picker' | 组件类型 |
233
+ | name | string | 变量名 |
234
+ | content | string | 内容 |
235
+ | cosmic-ai-input-placeholder | string | 占位符文本 |
236
+
237
+ ### AiInputRef
238
+
239
+ | 方法 | 类型 | 描述 |
240
+ |------|------|------|
241
+ | getCurrentValue | () => string | 获取当前输入值 |
242
+
243
+ ## TypeScript 支持
244
+
245
+ 本组件完全支持 TypeScript,并提供了完整的类型定义。所有组件属性和方法都有类型检查,可以在开发过程中获得更好的代码提示和错误检测。
246
+
247
+ ### 类型定义
248
+
249
+ ```typescript
250
+ import React from 'react';
251
+
252
+ export interface BaseInputItem {
253
+ name: string;
254
+ content: string;
255
+ cosmic-ai-input-placeholder: string;
256
+ }
257
+
258
+ export interface InputItem extends BaseInputItem {
259
+ type: 'input';
260
+ }
261
+
262
+ export interface SelectItem extends BaseInputItem {
263
+ type: 'select';
264
+ options: string[];
265
+ }
266
+
267
+ export interface MultipleSelectItem extends BaseInputItem {
268
+ type: 'multiple-select';
269
+ options: string[];
270
+ }
271
+
272
+ export interface DatePickerItem extends BaseInputItem {
273
+ type: 'date-picker';
274
+ }
275
+
276
+ export type VarItem = InputItem | SelectItem | MultipleSelectItem | DatePickerItem;
277
+
278
+ export interface AiInputProps {
279
+ value?: string;
280
+ varList: VarItem[];
281
+ cosmic-ai-input-placeholder?: string;
282
+ maxLength?: 1 | 2 | 3 | 4;
283
+ defaultRows?: number;
284
+ disabled?: boolean;
285
+ onParse?: (parsedValue: string) => void;
286
+ onSend?: (value: string) => void;
287
+ onMaxLengthExceeded?: (value: string, maxLength: number) => void;
288
+ onFocus?: (e: React.FocusEvent) => void;
289
+ onBlur?: (e: React.FocusEvent) => void;
290
+ onChange?: (value: string) => void;
291
+ onClick?: (e: React.MouseEvent) => void;
292
+ onKeyDown?: (e: React.KeyboardEvent) => void;
293
+ onKeyUp?: (e: React.KeyboardEvent) => void;
294
+ }
295
+
296
+ export interface AiInputRef {
297
+ getCurrentValue: () => string;
298
+ }
299
+ ```
@@ -0,0 +1,3 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const u=require("react/jsx-runtime"),a=require("react"),Fe=require("classnames"),Oe=require("react-dom"),ae=a.forwardRef(({value:c,position:r,id:s,onChange:h},S)=>{const[g,E]=a.useState(!0),m=a.useRef(null),C=a.useRef(null);a.useEffect(()=>{typeof S=="function"?S(m.current):S&&(S.current=m.current)},[S]);const w=d=>{console.log("DatePicker handleChange",d);const N=d.target.value;h==null||h(N,"date-picker")};a.useEffect(()=>{if(C.current&&g)try{setTimeout(()=>{R()},0)}catch(d){console.log("无法自动打开日期选择器,浏览器安全策略限制",d)}},[g]);const R=()=>{if(C.current)try{C.current.showPicker()}catch(d){console.log("点击后无法打开日期选择器",d)}},b=d=>{d.stopPropagation(),console.log("DatePicker handleClick",d)};return g?u.jsx("div",{ref:m,id:s,style:{top:(r==null?void 0:r.top)||0,left:(r==null?void 0:r.left)||0},className:"cosmic-ai-input-datePicker",suppressHydrationWarning:!0,children:u.jsx("input",{ref:C,type:"date",onChange:w,onClick:b})}):null});ae.displayName="DatePicker";function X(c){const r=c.textContent||"",s=c.nextSibling;r.length?(s==null||s.setAttribute("style","display: none"),c.style.padding="2px 4px",c.style.borderTopLeftRadius="2px",c.style.borderBottomLeftRadius="2px",c.style.borderTopRightRadius="2px",c.style.borderBottomRightRadius="2px"):(s==null||s.setAttribute("style","display: inline"),c.style.padding="2px 0 2px 4px",c.style.borderTopLeftRadius="2px",c.style.borderBottomLeftRadius="2px",c.style.borderTopRightRadius="0",c.style.borderBottomRightRadius="0")}function L(c){if(c&&c.getAttribute("data-set-type")==="input"){const r=c.children[0];r.setAttribute("contenteditable","true"),requestAnimationFrame(()=>{r.focus()})}}function ie(c){c&&c.getAttribute("data-set-type")==="input"&&c.children[0].setAttribute("contenteditable","false")}function F(c){return c&&c.getAttribute("data-set-type")==="input"}const de=a.forwardRef(({options:c,value:r,position:s,id:h,height:S=37,onChange:g},E)=>{const[m,C]=a.useState(r||""),w=a.useRef(null);a.useEffect(()=>{typeof E=="function"?E(w.current):E&&(E.current=w.current)},[E]);const R=d=>{const N=m.split(",").filter(D=>D)||[];let A="";N.includes(d)?A=N.filter(D=>D!==d).join(","):(console.log("handleOptionClick",N),N.length?A=`${N.join(",")},${d}`:A=d),C(A),g==null||g(A,"multiple-select")},b=m.split(",")||[];return u.jsx("div",{ref:w,className:"cosmic-ai-input-selectFloatElement",id:h,style:{position:"absolute",top:(s==null?void 0:s.top)||0,left:(s==null?void 0:s.left)||0,zIndex:5e3,maxHeight:`${S}px`},children:c.map((d,N)=>u.jsx("div",{className:`selectOption ${b.includes(d)?"selected":""}`,onClick:()=>R(d),children:d},N))})});de.displayName="MultipleSelect";const ue=a.forwardRef(({options:c,value:r,position:s,id:h,height:S=120,onChange:g},E)=>{const[m,C]=a.useState(r||""),w=a.useRef(null);a.useEffect(()=>{typeof E=="function"?E(w.current):E&&(E.current=w.current)},[E]);const R=b=>{C(b),g==null||g(b,"select")};return u.jsx("div",{ref:w,className:"cosmic-ai-input-selectFloatElement",id:h,style:{position:"absolute",top:(s==null?void 0:s.top)||0,left:(s==null?void 0:s.left)||0,zIndex:5e3,maxHeight:`${S}px`},children:c.map((b,d)=>u.jsx("div",{className:`selectOption ${m===b?"selected":""}`,onClick:()=>R(b),children:b},d))})});ue.displayName="Select";function re(c){const r=c instanceof Element?c:document.getElementById(c);return r&&r.children[0].textContent||""}function Me(c,r){const s=c instanceof Element?c:document.getElementById(c);s&&(s.children[0].textContent=r)}function q(c){const r=document.createRange(),s=window.getSelection();if(!s){console.error("无法获取selection对象");return}r.selectNodeContents(c),r.collapse(!0),s.removeAllRanges(),s.addRange(r)}function B(c){const r=document.createRange(),s=window.getSelection();if(!s){console.error("无法获取selection对象");return}r.selectNodeContents(c),r.collapse(!1),s.removeAllRanges(),s.addRange(r)}function G(c){const r=window.getSelection();if(!r||r.rangeCount===0)return 0;const s=r.getRangeAt(0),h=s.cloneRange();return h.selectNodeContents(c),h.setEnd(s.startContainer,s.startOffset),h.toString().length}function $e(){const c=window.getSelection();if(!c||c.rangeCount===0)return null;const s=c.getRangeAt(0).startContainer;return s.nodeType===Node.TEXT_NODE?s.parentElement:s.nodeType===Node.ELEMENT_NODE?s:null}function qe(){const c=window.getSelection();if(!c||c.rangeCount===0)return null;const r=c.getRangeAt(0),s=r.startContainer,h=r.startOffset;return s.nodeType===Node.TEXT_NODE?h>0?s:s.previousSibling:s.nodeType===Node.ELEMENT_NODE?h>0?s.childNodes[h-1]:s.previousSibling:null}function Be(){const c=window.getSelection();if(!c||c.rangeCount===0)return null;const r=c.getRangeAt(0),s=r.startContainer,h=r.startOffset;return s.nodeType===Node.TEXT_NODE?h<s.length?s:s.nextSibling:s.nodeType===Node.ELEMENT_NODE?h<s.childNodes.length?s.childNodes[h]:s.nextSibling:null}function Ve(c){return c&&!c.getAttribute("data-set-type")}const pe=a.forwardRef((c,r)=>{const{value:s,varList:h,placeholder:S="",maxLength:g,defaultRows:E=3,disabled:m=!1,onFocus:C,onBlur:w,onChange:R,onClick:b,onSend:d,onParse:N,onKeyDown:A,onKeyUp:D,onMaxLengthExceeded:V}=c,[J,He]=a.useState(s||""),[Ke,Q]=a.useState(s||""),[he,Y]=a.useState(""),[H,O]=a.useState(!1),[K,W]=a.useState({top:0,left:0}),[Z,v]=a.useState([]),[_,I]=a.useState(""),[j,ee]=a.useState(null),[te,ne]=a.useState(120),fe=240,ge=240,le=240,oe=276,M=a.useRef(null),x=a.useRef(null),T=a.useRef(null),$=()=>{var e;return((e=M.current)==null?void 0:e.innerText)||""},se=()=>{var e;return((e=M.current)==null?void 0:e.innerHTML)||""},ye=e=>{const n=[];let t=0;const o=/\[([^\]]+)\]/g;let p,f=0;const k=new Set(h.map(y=>y.name));for(;(p=o.exec(e))!==null;){if(p.index>t){const i=e.substring(t,p.index).split(`
2
+ `);i.forEach((P,Le)=>{P&&n.push({type:"text",content:P,id:`text-${f++}`}),Le<i.length-1&&n.push({type:"newline",id:`newline-${f++}`})})}const y=p[1];if(k.has(y)){const l=h.find(i=>i.name===y);(l==null?void 0:l.type)==="input"?n.push({type:"input",name:l==null?void 0:l.name,content:(l==null?void 0:l.content)||"",placeholder:(l==null?void 0:l.placeholder)||y,id:`input-${f++}`}):(l==null?void 0:l.type)==="select"?n.push({type:"select",name:l==null?void 0:l.name,content:(l==null?void 0:l.content)||"",placeholder:(l==null?void 0:l.placeholder)||y,options:(l==null?void 0:l.options)||[],id:`select-${f++}`}):(l==null?void 0:l.type)==="multiple-select"?n.push({type:"multiple-select",name:l==null?void 0:l.name,content:(l==null?void 0:l.content)||"",placeholder:(l==null?void 0:l.placeholder)||y,options:(l==null?void 0:l.options)||[],id:`multiple-select-${f++}`}):(l==null?void 0:l.type)==="date-picker"&&n.push({type:"date-picker",name:l==null?void 0:l.name,content:(l==null?void 0:l.content)||"",placeholder:(l==null?void 0:l.placeholder)||y,id:`date-picker-${f++}`})}else n.push({type:"text",content:`[${y}]`,id:`text-${f++}`});t=o.lastIndex}if(t<e.length){const l=e.substring(t).split(`
3
+ `);l.forEach((i,P)=>{i&&n.push({type:"text",content:i,id:`text-${f++}`}),P<l.length-1&&n.push({type:"newline",id:`newline-${f++}`})})}return n},z=()=>{var e;(e=M.current)==null||e.setAttribute("contenteditable","true"),x.current&&(F(x.current)&&x.current.children[0].setAttribute("contenteditable","false"),x.current=null)},xe=e=>{console.log("handleEditorClick",e),b==null||b(e)},Ee=e=>{console.log("handleEditorMouseDown",e),z()},be=e=>{console.log("handleEditorInput",e),Q($()),Y(se()),R==null||R($())},we=e=>{if(e.code==="Enter"&&!e.shiftKey){e.preventDefault();const n=$();console.log("onSend",n,"maxLength:",g,"length:",n.length),g?n.length<=g?d==null||d(n):(console.log("maxLength exceeded",n,g),V==null||V(n,g)):d==null||d(n)}},Ce=e=>{var t;console.log("handleEditorKeyDown",e),A==null||A(e);const n=$e();if(n&&Ve(n)){if(e.code==="ArrowLeft"){const o=n==null?void 0:n.previousElementSibling,p=G(n);o&&p===0&&F(o)&&o.children[0]&&(x.current=o,L(o),requestAnimationFrame(()=>{B(o.children[0])}))}if(e.code==="ArrowRight"){const o=n==null?void 0:n.nextElementSibling,p=G(n);o&&p===((t=n.textContent)==null?void 0:t.length)&&F(o)&&o.children[0]&&(x.current=o,L(o),requestAnimationFrame(()=>{q(o.children[0])}))}}if(n&&n.getAttribute("data-set-type")==="container"){if(e.code==="ArrowLeft"){const o=qe();F(o)&&o.children[0]&&(x.current=o,L(o),requestAnimationFrame(()=>{B(o.children[0])}))}if(e.code==="ArrowRight"){const o=Be();F(o)&&o.children[0]&&(x.current=o,L(o),requestAnimationFrame(()=>{q(o.children[0])}))}}we(e)},Re=e=>{console.log("handleEditorKeyUp",e),D==null||D(e)},Ae=(e,n)=>{n.stopPropagation(),console.log("handleInputClick",e)},Se=(e,n)=>{var o;n.stopPropagation(),console.log("handleInputMouseDown",e,n),x.current&&ie(x.current),(o=M.current)==null||o.setAttribute("contenteditable","false");const t=document.getElementById(e.id);x.current=t,requestAnimationFrame(()=>{L(t)})},ke=(e,n)=>{var p,f,k,y,l;console.log("handleInputKeyDown",e,n),A==null||A(n),n.stopPropagation();const t=n.target,o=G(t);if(n.code==="Backspace"&&o===0){const i=(p=t.parentElement)==null?void 0:p.previousElementSibling;console.log("previousElement",i),i&&(F(i)&&i.children[0]&&((f=i.children[0].textContent)!=null&&f.length)?(x.current=i,L(i),B(i.children[0]),requestAnimationFrame(()=>{X(i.children[0])})):(z(),B(i)))}if(n.code==="ArrowRight"&&o===((k=t.textContent)==null?void 0:k.length)){const i=(y=t.parentElement)==null?void 0:y.nextElementSibling;console.log("nextElement",i),i&&(F(i)&&i.children[0]&&((l=i.children[0].textContent)!=null&&l.length)?(x.current=i,L(i),q(i.children[0]),requestAnimationFrame(()=>{X(i.children[0])})):(z(),q(i)))}},me=(e,n)=>{console.log("handleInputKeyUp",e,n),D==null||D(n);const t=n.target;X(t)},Ne=(e,n)=>{var o;n.stopPropagation(),console.log("handlePlaceholderMouseDown",e),x.current&&ie(x.current),(o=M.current)==null||o.setAttribute("contenteditable","false");const t=document.getElementById(e.id);x.current=t,requestAnimationFrame(()=>{L(t)})},De=(e,n)=>{console.log("handleInputChange",e,n),Q($()),Y(se()),R==null||R($())},Te=(e,n)=>{console.log("handleTextSpanKeyDown 不生效",e,n)};a.useEffect(()=>{if(!H)return;const e=o=>{T.current&&!T.current.contains(o.target)&&O(!1)},n=o=>{T.current&&!T.current.contains(o.target)&&O(!1)},t=()=>{O(!1)};return document.addEventListener("mousedown",e),document.addEventListener("scroll",n,!0),window.addEventListener("resize",t),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("scroll",n,!0),window.removeEventListener("resize",t)}},[H]);const U=(e,n)=>{if(console.log("handleFloatChange",e,n),j&&Me(j.id,e),n==="select"&&O(!1),n==="multiple-select"||n==="date-picker"){const t=document.getElementById(j.id);t&&t.children[0]&&t.children[1]&&(e.length>0?(t.children[0].setAttribute("style","display: inline"),t.children[0].setAttribute("contenteditable","false"),t.children[1].setAttribute("style","display: none"),t.children[1].setAttribute("contenteditable","true")):(t.children[0].setAttribute("style","display: none"),t.children[0].setAttribute("contenteditable","true"),t.children[1].setAttribute("style","display: inline"),t.children[1].setAttribute("contenteditable","true")))}},ce=(e,n)=>{console.log("handleSelectClick",e,n);const o=n.target.getBoundingClientRect();v(e.options),I(e.value||re(e.id)),W({top:-999999,left:-999999999}),ee(e),ne(ge),O(!0),requestAnimationFrame(()=>{if(T.current){console.log("currentFloatElementRef.current",T.current);const p=T.current.getBoundingClientRect();let f=o.left,k=o.top+o.height;window.innerWidth-o.right<fe&&o.width<p.width&&(f=o.right-p.width),o.top<p.height&&(k=o.top+o.height),W({top:k,left:f}),ne(p.height)}})},je=(e,n)=>{console.log("handleDatePickerClick",e,n);const o=n.target.getBoundingClientRect();let p=o.left,f=o.top-oe;window.innerWidth-o.right<le&&(p=p-le+o.width),o.top<oe&&(f=o.top+o.height),v(e.options),I(e.value||re(e.id)),W({top:f,left:p}),ee(e),O(!0)},Pe=()=>{const e=ye(J);console.log("parsed",e);const n=[];return e.forEach(t=>{var o,p,f,k,y,l;if(t.type==="text")n.push(u.jsx("span",{onKeyDown:i=>Te(t,i),children:t.content},t.id));else if(t.type==="newline")n.push(u.jsx("br",{},t.id));else if(t.type==="input")n.push(u.jsxs("span",{id:t.id,"data-set-type":"input",contentEditable:!1,suppressContentEditableWarning:!0,onInput:i=>De(t,i),onClick:i=>Ae(t,i),onMouseDown:i=>Se(t,i),"data-cosmic-ai-input-placeholder":t.placeholder,children:[u.jsx("span",{className:"cosmic-ai-input-inputContent",style:{padding:(o=t.content)!=null&&o.length?"2px 4px":"2px 0 2px 4px"},contentEditable:!1,onKeyDown:i=>ke(t,i),onKeyUp:i=>me(t,i),children:t.content}),u.jsx("span",{contentEditable:!1,style:{display:(p=t.content)!=null&&p.length?"none":"inline"},className:"cosmic-ai-input-placeholder",onMouseDown:i=>Ne(t,i),children:t.placeholder})]},t.id));else if(t.type==="select"){const i=t.content||((f=t.options)==null?void 0:f[0])||t.placeholder;n.push(u.jsx("span",{id:t.id,"data-set-type":"select",contentEditable:!0,suppressContentEditableWarning:!0,onClick:P=>ce(t,P),"data-cosmic-ai-input-placeholder":t.placeholder,children:u.jsx("span",{contentEditable:!1,children:i})},t.id))}else if(t.type==="multiple-select"){const i=t.content||((k=t.options)==null?void 0:k[0]);n.push(u.jsxs("span",{id:t.id,"data-set-type":"multiple-select",contentEditable:!0,suppressContentEditableWarning:!0,onClick:P=>ce(t,P),"data-cosmic-ai-input-placeholder":t.placeholder,children:[u.jsx("span",{style:{display:i!=null&&i.length?"inline":"none"},contentEditable:!1,children:i}),u.jsx("span",{style:{display:i!=null&&i.length?"none":"inline"},className:"cosmic-ai-input-selectPlaceholder",contentEditable:!1,children:t.placeholder})]},t.id))}else t.type==="date-picker"&&n.push(u.jsxs("span",{id:t.id,"data-set-type":"date-picker",contentEditable:!0,suppressContentEditableWarning:!0,onClick:i=>je(t,i),"data-cosmic-ai-input-placeholder":t.placeholder,children:[u.jsx("span",{style:{display:(y=t.content)!=null&&y.length?"inline":"none"},contentEditable:!1,children:t.content}),u.jsx("span",{style:{display:(l=t.content)!=null&&l.length?"none":"inline"},className:"cosmic-ai-input-datePickerPlaceholder",contentEditable:!1,children:t.placeholder})]},t.id))}),n};return a.useImperativeHandle(r,()=>({getCurrentValue:$})),u.jsxs(u.Fragment,{children:[u.jsx("div",{"data-set-type":"container","data-cosmic-ai-input-placeholder":S,className:Fe("cosmic-ai-input",`cosmic-ai-input-rows${E}`,{"is-disabled":m},{"is-empty":J.length===0||he==="<br>"}),ref:M,contentEditable:!0,suppressContentEditableWarning:!0,onClick:e=>xe(e),onFocus:e=>{C==null||C(e)},onBlur:e=>{w==null||w(e)},onMouseDown:e=>Ee(e),onKeyDown:e=>Ce(e),onKeyUp:e=>Re(e),onInput:e=>be(e),children:Pe()}),H&&Oe.createPortal((j==null?void 0:j.type)==="multiple-select"?u.jsx(de,{ref:T,options:Z,value:_,position:K,height:te,onChange:U},"multiple-select"):(j==null?void 0:j.type)==="date-picker"?u.jsx(ae,{ref:T,value:_,position:K,onChange:U},"date-picker"):u.jsx(ue,{ref:T,options:Z,value:_,position:K,height:te,onChange:U},"select"),document.body)]})});pe.displayName="AiInput";exports.default=pe;
@@ -0,0 +1,54 @@
1
+ import { default as default_2 } from 'react';
2
+
3
+ declare const AiInput: default_2.ForwardRefExoticComponent<AiInputProps & default_2.RefAttributes<AiInputRef>>;
4
+ export default AiInput;
5
+
6
+ declare interface AiInputProps {
7
+ value?: string;
8
+ varList: (InputItem | SelectItem | MultipleSelectItem | DatePickerItem)[];
9
+ placeholder?: string;
10
+ maxLength?: 1 | 2 | 3 | 4 | undefined;
11
+ defaultRows?: number;
12
+ disabled?: boolean;
13
+ onParse?: (parsedValue: string) => void;
14
+ onSend?: (value: string) => void;
15
+ onMaxLengthExceeded?: (value: string, maxLength: number) => void;
16
+ onFocus?: (e: default_2.FocusEvent) => void;
17
+ onBlur?: (e: default_2.FocusEvent) => void;
18
+ onChange?: (value: string) => void;
19
+ onClick?: (e: default_2.MouseEvent) => void;
20
+ onKeyDown?: (e: default_2.KeyboardEvent) => void;
21
+ onKeyUp?: (e: default_2.KeyboardEvent) => void;
22
+ }
23
+
24
+ export declare interface AiInputRef {
25
+ getCurrentValue: () => string;
26
+ }
27
+
28
+ declare interface DatePickerItem {
29
+ type: 'date-picker';
30
+ name: string;
31
+ content: string;
32
+ placeholder: string;
33
+ }
34
+
35
+ declare interface InputItem {
36
+ type: 'input';
37
+ name: string;
38
+ content: string;
39
+ placeholder: string;
40
+ }
41
+
42
+ declare interface MultipleSelectItem extends Omit<SelectItem, 'type'> {
43
+ type: 'multiple-select';
44
+ }
45
+
46
+ declare interface SelectItem {
47
+ type: 'select';
48
+ name: string;
49
+ content: string;
50
+ placeholder: string;
51
+ options: string[];
52
+ }
53
+
54
+ export { }
@@ -0,0 +1,573 @@
1
+ import { jsx as h, jsxs as q, Fragment as Be } from "react/jsx-runtime";
2
+ import { forwardRef as _, useState as A, useRef as $, useEffect as H, useImperativeHandle as Ve } from "react";
3
+ import He from "classnames";
4
+ import { createPortal as qe } from "react-dom";
5
+ const he = _(
6
+ ({ value: s, position: r, id: c, onChange: u }, k) => {
7
+ const [f, E] = A(!0), N = $(null), w = $(null);
8
+ H(() => {
9
+ typeof k == "function" ? k(N.current) : k && (k.current = N.current);
10
+ }, [k]);
11
+ const x = (a) => {
12
+ console.log("DatePicker handleChange", a);
13
+ const S = a.target.value;
14
+ u == null || u(S, "date-picker");
15
+ };
16
+ H(() => {
17
+ if (w.current && f)
18
+ try {
19
+ setTimeout(() => {
20
+ C();
21
+ }, 0);
22
+ } catch (a) {
23
+ console.log("无法自动打开日期选择器,浏览器安全策略限制", a);
24
+ }
25
+ }, [f]);
26
+ const C = () => {
27
+ if (w.current)
28
+ try {
29
+ w.current.showPicker();
30
+ } catch (a) {
31
+ console.log("点击后无法打开日期选择器", a);
32
+ }
33
+ }, b = (a) => {
34
+ a.stopPropagation(), console.log("DatePicker handleClick", a);
35
+ };
36
+ return f ? /* @__PURE__ */ h(
37
+ "div",
38
+ {
39
+ ref: N,
40
+ id: c,
41
+ style: {
42
+ top: (r == null ? void 0 : r.top) || 0,
43
+ left: (r == null ? void 0 : r.left) || 0
44
+ },
45
+ className: "cosmic-ai-input-datePicker",
46
+ suppressHydrationWarning: !0,
47
+ children: /* @__PURE__ */ h("input", { ref: w, type: "date", onChange: x, onClick: b })
48
+ }
49
+ ) : null;
50
+ }
51
+ );
52
+ he.displayName = "DatePicker";
53
+ function Y(s) {
54
+ const r = s.textContent || "", c = s.nextSibling;
55
+ r.length ? (c == null || c.setAttribute("style", "display: none"), s.style.padding = "2px 4px", s.style.borderTopLeftRadius = "2px", s.style.borderBottomLeftRadius = "2px", s.style.borderTopRightRadius = "2px", s.style.borderBottomRightRadius = "2px") : (c == null || c.setAttribute("style", "display: inline"), s.style.padding = "2px 0 2px 4px", s.style.borderTopLeftRadius = "2px", s.style.borderBottomLeftRadius = "2px", s.style.borderTopRightRadius = "0", s.style.borderBottomRightRadius = "0");
56
+ }
57
+ function F(s) {
58
+ if (s && s.getAttribute("data-set-type") === "input") {
59
+ const r = s.children[0];
60
+ r.setAttribute("contenteditable", "true"), requestAnimationFrame(() => {
61
+ r.focus();
62
+ });
63
+ }
64
+ }
65
+ function ue(s) {
66
+ s && s.getAttribute("data-set-type") === "input" && s.children[0].setAttribute("contenteditable", "false");
67
+ }
68
+ function O(s) {
69
+ return s && s.getAttribute("data-set-type") === "input";
70
+ }
71
+ const fe = _(({
72
+ options: s,
73
+ value: r,
74
+ position: c,
75
+ id: u,
76
+ height: k = 37,
77
+ onChange: f
78
+ }, E) => {
79
+ const [N, w] = A(r || ""), x = $(null);
80
+ H(() => {
81
+ typeof E == "function" ? E(x.current) : E && (E.current = x.current);
82
+ }, [E]);
83
+ const C = (a) => {
84
+ const S = N.split(",").filter((D) => D) || [];
85
+ let m = "";
86
+ S.includes(a) ? m = S.filter((D) => D !== a).join(",") : (console.log("handleOptionClick", S), S.length ? m = `${S.join(",")},${a}` : m = a), w(m), f == null || f(m, "multiple-select");
87
+ }, b = N.split(",") || [];
88
+ return /* @__PURE__ */ h(
89
+ "div",
90
+ {
91
+ ref: x,
92
+ className: "cosmic-ai-input-selectFloatElement",
93
+ id: u,
94
+ style: {
95
+ position: "absolute",
96
+ top: (c == null ? void 0 : c.top) || 0,
97
+ left: (c == null ? void 0 : c.left) || 0,
98
+ zIndex: 5e3,
99
+ maxHeight: `${k}px`
100
+ },
101
+ children: s.map((a, S) => /* @__PURE__ */ h(
102
+ "div",
103
+ {
104
+ className: `selectOption ${b.includes(a) ? "selected" : ""}`,
105
+ onClick: () => C(a),
106
+ children: a
107
+ },
108
+ S
109
+ ))
110
+ }
111
+ );
112
+ });
113
+ fe.displayName = "MultipleSelect";
114
+ const ge = _(({
115
+ options: s,
116
+ value: r,
117
+ position: c,
118
+ id: u,
119
+ height: k = 120,
120
+ onChange: f
121
+ }, E) => {
122
+ const [N, w] = A(r || ""), x = $(null);
123
+ H(() => {
124
+ typeof E == "function" ? E(x.current) : E && (E.current = x.current);
125
+ }, [E]);
126
+ const C = (b) => {
127
+ w(b), f == null || f(b, "select");
128
+ };
129
+ return /* @__PURE__ */ h(
130
+ "div",
131
+ {
132
+ ref: x,
133
+ className: "cosmic-ai-input-selectFloatElement",
134
+ id: u,
135
+ style: {
136
+ position: "absolute",
137
+ top: (c == null ? void 0 : c.top) || 0,
138
+ left: (c == null ? void 0 : c.left) || 0,
139
+ zIndex: 5e3,
140
+ maxHeight: `${k}px`
141
+ },
142
+ children: s.map((b, a) => /* @__PURE__ */ h(
143
+ "div",
144
+ {
145
+ className: `selectOption ${N === b ? "selected" : ""}`,
146
+ onClick: () => C(b),
147
+ children: b
148
+ },
149
+ a
150
+ ))
151
+ }
152
+ );
153
+ });
154
+ ge.displayName = "Select";
155
+ function pe(s) {
156
+ const r = s instanceof Element ? s : document.getElementById(s);
157
+ return r && r.children[0].textContent || "";
158
+ }
159
+ function Ke(s, r) {
160
+ const c = s instanceof Element ? s : document.getElementById(s);
161
+ c && (c.children[0].textContent = r);
162
+ }
163
+ function K(s) {
164
+ const r = document.createRange(), c = window.getSelection();
165
+ if (!c) {
166
+ console.error("无法获取selection对象");
167
+ return;
168
+ }
169
+ r.selectNodeContents(s), r.collapse(!0), c.removeAllRanges(), c.addRange(r);
170
+ }
171
+ function W(s) {
172
+ const r = document.createRange(), c = window.getSelection();
173
+ if (!c) {
174
+ console.error("无法获取selection对象");
175
+ return;
176
+ }
177
+ r.selectNodeContents(s), r.collapse(!1), c.removeAllRanges(), c.addRange(r);
178
+ }
179
+ function Z(s) {
180
+ const r = window.getSelection();
181
+ if (!r || r.rangeCount === 0)
182
+ return 0;
183
+ const c = r.getRangeAt(0), u = c.cloneRange();
184
+ return u.selectNodeContents(s), u.setEnd(c.startContainer, c.startOffset), u.toString().length;
185
+ }
186
+ function We() {
187
+ const s = window.getSelection();
188
+ if (!s || s.rangeCount === 0)
189
+ return null;
190
+ const c = s.getRangeAt(0).startContainer;
191
+ return c.nodeType === Node.TEXT_NODE ? c.parentElement : c.nodeType === Node.ELEMENT_NODE ? c : null;
192
+ }
193
+ function _e() {
194
+ const s = window.getSelection();
195
+ if (!s || s.rangeCount === 0)
196
+ return null;
197
+ const r = s.getRangeAt(0), c = r.startContainer, u = r.startOffset;
198
+ return c.nodeType === Node.TEXT_NODE ? u > 0 ? c : c.previousSibling : c.nodeType === Node.ELEMENT_NODE ? u > 0 ? c.childNodes[u - 1] : c.previousSibling : null;
199
+ }
200
+ function ze() {
201
+ const s = window.getSelection();
202
+ if (!s || s.rangeCount === 0)
203
+ return null;
204
+ const r = s.getRangeAt(0), c = r.startContainer, u = r.startOffset;
205
+ return c.nodeType === Node.TEXT_NODE ? u < c.length ? c : c.nextSibling : c.nodeType === Node.ELEMENT_NODE ? u < c.childNodes.length ? c.childNodes[u] : c.nextSibling : null;
206
+ }
207
+ function je(s) {
208
+ return s && !s.getAttribute("data-set-type");
209
+ }
210
+ const Ue = _((s, r) => {
211
+ const { value: c, varList: u, placeholder: k = "", maxLength: f, defaultRows: E = 3, disabled: N = !1, onFocus: w, onBlur: x, onChange: C, onClick: b, onSend: a, onParse: S, onKeyDown: m, onKeyUp: D, onMaxLengthExceeded: z } = s, [I, Xe] = A(c || ""), [Ge, v] = A(c || ""), [ye, ee] = A(""), [j, M] = A(!1), [U, X] = A({ top: 0, left: 0 }), [te, ne] = A([]), [G, le] = A(""), [P, oe] = A(null), [ce, se] = A(120), Ee = 240, be = 240, ie = 240, re = 276, B = $(null), y = $(null), T = $(null), V = () => {
212
+ var e;
213
+ return ((e = B.current) == null ? void 0 : e.innerText) || "";
214
+ }, ae = () => {
215
+ var e;
216
+ return ((e = B.current) == null ? void 0 : e.innerHTML) || "";
217
+ }, xe = (e) => {
218
+ const n = [];
219
+ let t = 0;
220
+ const o = /\[([^\]]+)\]/g;
221
+ let d, p = 0;
222
+ const R = new Set(u.map((g) => g.name));
223
+ for (; (d = o.exec(e)) !== null; ) {
224
+ if (d.index > t) {
225
+ const i = e.substring(t, d.index).split(`
226
+ `);
227
+ i.forEach((L, Me) => {
228
+ L && n.push({
229
+ type: "text",
230
+ content: L,
231
+ id: `text-${p++}`
232
+ }), Me < i.length - 1 && n.push({
233
+ type: "newline",
234
+ id: `newline-${p++}`
235
+ });
236
+ });
237
+ }
238
+ const g = d[1];
239
+ if (R.has(g)) {
240
+ const l = u.find((i) => i.name === g);
241
+ (l == null ? void 0 : l.type) === "input" ? n.push({
242
+ type: "input",
243
+ name: l == null ? void 0 : l.name,
244
+ content: (l == null ? void 0 : l.content) || "",
245
+ placeholder: (l == null ? void 0 : l.placeholder) || g,
246
+ id: `input-${p++}`
247
+ }) : (l == null ? void 0 : l.type) === "select" ? n.push({
248
+ type: "select",
249
+ name: l == null ? void 0 : l.name,
250
+ content: (l == null ? void 0 : l.content) || "",
251
+ placeholder: (l == null ? void 0 : l.placeholder) || g,
252
+ options: (l == null ? void 0 : l.options) || [],
253
+ id: `select-${p++}`
254
+ }) : (l == null ? void 0 : l.type) === "multiple-select" ? n.push({
255
+ type: "multiple-select",
256
+ name: l == null ? void 0 : l.name,
257
+ content: (l == null ? void 0 : l.content) || "",
258
+ placeholder: (l == null ? void 0 : l.placeholder) || g,
259
+ options: (l == null ? void 0 : l.options) || [],
260
+ id: `multiple-select-${p++}`
261
+ }) : (l == null ? void 0 : l.type) === "date-picker" && n.push({
262
+ type: "date-picker",
263
+ name: l == null ? void 0 : l.name,
264
+ content: (l == null ? void 0 : l.content) || "",
265
+ placeholder: (l == null ? void 0 : l.placeholder) || g,
266
+ id: `date-picker-${p++}`
267
+ });
268
+ } else
269
+ n.push({
270
+ type: "text",
271
+ content: `[${g}]`,
272
+ id: `text-${p++}`
273
+ });
274
+ t = o.lastIndex;
275
+ }
276
+ if (t < e.length) {
277
+ const l = e.substring(t).split(`
278
+ `);
279
+ l.forEach((i, L) => {
280
+ i && n.push({
281
+ type: "text",
282
+ content: i,
283
+ id: `text-${p++}`
284
+ }), L < l.length - 1 && n.push({
285
+ type: "newline",
286
+ id: `newline-${p++}`
287
+ });
288
+ });
289
+ }
290
+ return n;
291
+ }, J = () => {
292
+ var e;
293
+ (e = B.current) == null || e.setAttribute("contenteditable", "true"), y.current && (O(y.current) && y.current.children[0].setAttribute("contenteditable", "false"), y.current = null);
294
+ }, we = (e) => {
295
+ console.log("handleEditorClick", e), b == null || b(e);
296
+ }, Ce = (e) => {
297
+ console.log("handleEditorMouseDown", e), J();
298
+ }, me = (e) => {
299
+ console.log("handleEditorInput", e), v(V()), ee(ae()), C == null || C(V());
300
+ }, Ae = (e) => {
301
+ if (e.code === "Enter" && !e.shiftKey) {
302
+ e.preventDefault();
303
+ const n = V();
304
+ console.log("onSend", n, "maxLength:", f, "length:", n.length), f ? n.length <= f ? a == null || a(n) : (console.log("maxLength exceeded", n, f), z == null || z(n, f)) : a == null || a(n);
305
+ }
306
+ }, ke = (e) => {
307
+ var t;
308
+ console.log("handleEditorKeyDown", e), m == null || m(e);
309
+ const n = We();
310
+ if (n && je(n)) {
311
+ if (e.code === "ArrowLeft") {
312
+ const o = n == null ? void 0 : n.previousElementSibling, d = Z(n);
313
+ o && d === 0 && O(o) && o.children[0] && (y.current = o, F(o), requestAnimationFrame(() => {
314
+ W(o.children[0]);
315
+ }));
316
+ }
317
+ if (e.code === "ArrowRight") {
318
+ const o = n == null ? void 0 : n.nextElementSibling, d = Z(n);
319
+ o && d === ((t = n.textContent) == null ? void 0 : t.length) && O(o) && o.children[0] && (y.current = o, F(o), requestAnimationFrame(() => {
320
+ K(o.children[0]);
321
+ }));
322
+ }
323
+ }
324
+ if (n && n.getAttribute("data-set-type") === "container") {
325
+ if (e.code === "ArrowLeft") {
326
+ const o = _e();
327
+ O(o) && o.children[0] && (y.current = o, F(o), requestAnimationFrame(() => {
328
+ W(o.children[0]);
329
+ }));
330
+ }
331
+ if (e.code === "ArrowRight") {
332
+ const o = ze();
333
+ O(o) && o.children[0] && (y.current = o, F(o), requestAnimationFrame(() => {
334
+ K(o.children[0]);
335
+ }));
336
+ }
337
+ }
338
+ Ae(e);
339
+ }, Re = (e) => {
340
+ console.log("handleEditorKeyUp", e), D == null || D(e);
341
+ }, Ne = (e, n) => {
342
+ n.stopPropagation(), console.log("handleInputClick", e);
343
+ }, Se = (e, n) => {
344
+ var o;
345
+ n.stopPropagation(), console.log("handleInputMouseDown", e, n), y.current && ue(y.current), (o = B.current) == null || o.setAttribute("contenteditable", "false");
346
+ const t = document.getElementById(e.id);
347
+ y.current = t, requestAnimationFrame(() => {
348
+ F(t);
349
+ });
350
+ }, De = (e, n) => {
351
+ var d, p, R, g, l;
352
+ console.log("handleInputKeyDown", e, n), m == null || m(n), n.stopPropagation();
353
+ const t = n.target, o = Z(t);
354
+ if (n.code === "Backspace" && o === 0) {
355
+ const i = (d = t.parentElement) == null ? void 0 : d.previousElementSibling;
356
+ console.log("previousElement", i), i && (O(i) && i.children[0] && ((p = i.children[0].textContent) != null && p.length) ? (y.current = i, F(i), W(i.children[0]), requestAnimationFrame(() => {
357
+ Y(i.children[0]);
358
+ })) : (J(), W(i)));
359
+ }
360
+ if (n.code === "ArrowRight" && o === ((R = t.textContent) == null ? void 0 : R.length)) {
361
+ const i = (g = t.parentElement) == null ? void 0 : g.nextElementSibling;
362
+ console.log("nextElement", i), i && (O(i) && i.children[0] && ((l = i.children[0].textContent) != null && l.length) ? (y.current = i, F(i), K(i.children[0]), requestAnimationFrame(() => {
363
+ Y(i.children[0]);
364
+ })) : (J(), K(i)));
365
+ }
366
+ }, Te = (e, n) => {
367
+ console.log("handleInputKeyUp", e, n), D == null || D(n);
368
+ const t = n.target;
369
+ Y(t);
370
+ }, Pe = (e, n) => {
371
+ var o;
372
+ n.stopPropagation(), console.log("handlePlaceholderMouseDown", e), y.current && ue(y.current), (o = B.current) == null || o.setAttribute("contenteditable", "false");
373
+ const t = document.getElementById(e.id);
374
+ y.current = t, requestAnimationFrame(() => {
375
+ F(t);
376
+ });
377
+ }, Le = (e, n) => {
378
+ console.log("handleInputChange", e, n), v(V()), ee(ae()), C == null || C(V());
379
+ }, Fe = (e, n) => {
380
+ console.log("handleTextSpanKeyDown 不生效", e, n);
381
+ };
382
+ H(() => {
383
+ if (!j)
384
+ return;
385
+ const e = (o) => {
386
+ T.current && !T.current.contains(o.target) && M(!1);
387
+ }, n = (o) => {
388
+ T.current && !T.current.contains(o.target) && M(!1);
389
+ }, t = () => {
390
+ M(!1);
391
+ };
392
+ return document.addEventListener("mousedown", e), document.addEventListener("scroll", n, !0), window.addEventListener("resize", t), () => {
393
+ document.removeEventListener("mousedown", e), document.removeEventListener("scroll", n, !0), window.removeEventListener("resize", t);
394
+ };
395
+ }, [j]);
396
+ const Q = (e, n) => {
397
+ if (console.log("handleFloatChange", e, n), P && Ke(P.id, e), n === "select" && M(!1), n === "multiple-select" || n === "date-picker") {
398
+ const t = document.getElementById(P.id);
399
+ t && t.children[0] && t.children[1] && (e.length > 0 ? (t.children[0].setAttribute("style", "display: inline"), t.children[0].setAttribute("contenteditable", "false"), t.children[1].setAttribute("style", "display: none"), t.children[1].setAttribute("contenteditable", "true")) : (t.children[0].setAttribute("style", "display: none"), t.children[0].setAttribute("contenteditable", "true"), t.children[1].setAttribute("style", "display: inline"), t.children[1].setAttribute("contenteditable", "true")));
400
+ }
401
+ }, de = (e, n) => {
402
+ console.log("handleSelectClick", e, n);
403
+ const o = n.target.getBoundingClientRect();
404
+ ne(e.options), le(e.value || pe(e.id)), X({ top: -999999, left: -999999999 }), oe(e), se(be), M(!0), requestAnimationFrame(() => {
405
+ if (T.current) {
406
+ console.log("currentFloatElementRef.current", T.current);
407
+ const d = T.current.getBoundingClientRect();
408
+ let p = o.left, R = o.top + o.height;
409
+ window.innerWidth - o.right < Ee && o.width < d.width && (p = o.right - d.width), o.top < d.height && (R = o.top + o.height), X({ top: R, left: p }), se(d.height);
410
+ }
411
+ });
412
+ }, Oe = (e, n) => {
413
+ console.log("handleDatePickerClick", e, n);
414
+ const o = n.target.getBoundingClientRect();
415
+ let d = o.left, p = o.top - re;
416
+ window.innerWidth - o.right < ie && (d = d - ie + o.width), o.top < re && (p = o.top + o.height), ne(e.options), le(e.value || pe(e.id)), X({ top: p, left: d }), oe(e), M(!0);
417
+ }, $e = () => {
418
+ const e = xe(I);
419
+ console.log("parsed", e);
420
+ const n = [];
421
+ return e.forEach((t) => {
422
+ var o, d, p, R, g, l;
423
+ if (t.type === "text")
424
+ n.push(
425
+ /* @__PURE__ */ h("span", { onKeyDown: (i) => Fe(t, i), children: t.content }, t.id)
426
+ );
427
+ else if (t.type === "newline")
428
+ n.push(/* @__PURE__ */ h("br", {}, t.id));
429
+ else if (t.type === "input")
430
+ n.push(
431
+ /* @__PURE__ */ q(
432
+ "span",
433
+ {
434
+ id: t.id,
435
+ "data-set-type": "input",
436
+ contentEditable: !1,
437
+ suppressContentEditableWarning: !0,
438
+ onInput: (i) => Le(t, i),
439
+ onClick: (i) => Ne(t, i),
440
+ onMouseDown: (i) => Se(t, i),
441
+ "data-cosmic-ai-input-placeholder": t.placeholder,
442
+ children: [
443
+ /* @__PURE__ */ h("span", { className: "cosmic-ai-input-inputContent", style: { padding: (o = t.content) != null && o.length ? "2px 4px" : "2px 0 2px 4px" }, contentEditable: !1, onKeyDown: (i) => De(t, i), onKeyUp: (i) => Te(t, i), children: t.content }),
444
+ /* @__PURE__ */ h("span", { contentEditable: !1, style: { display: (d = t.content) != null && d.length ? "none" : "inline" }, className: "cosmic-ai-input-placeholder", onMouseDown: (i) => Pe(t, i), children: t.placeholder })
445
+ ]
446
+ },
447
+ t.id
448
+ )
449
+ );
450
+ else if (t.type === "select") {
451
+ const i = t.content || ((p = t.options) == null ? void 0 : p[0]) || t.placeholder;
452
+ n.push(
453
+ /* @__PURE__ */ h(
454
+ "span",
455
+ {
456
+ id: t.id,
457
+ "data-set-type": "select",
458
+ contentEditable: !0,
459
+ suppressContentEditableWarning: !0,
460
+ onClick: (L) => de(t, L),
461
+ "data-cosmic-ai-input-placeholder": t.placeholder,
462
+ children: /* @__PURE__ */ h("span", { contentEditable: !1, children: i })
463
+ },
464
+ t.id
465
+ )
466
+ );
467
+ } else if (t.type === "multiple-select") {
468
+ const i = t.content || ((R = t.options) == null ? void 0 : R[0]);
469
+ n.push(
470
+ /* @__PURE__ */ q(
471
+ "span",
472
+ {
473
+ id: t.id,
474
+ "data-set-type": "multiple-select",
475
+ contentEditable: !0,
476
+ suppressContentEditableWarning: !0,
477
+ onClick: (L) => de(t, L),
478
+ "data-cosmic-ai-input-placeholder": t.placeholder,
479
+ children: [
480
+ /* @__PURE__ */ h("span", { style: { display: i != null && i.length ? "inline" : "none" }, contentEditable: !1, children: i }),
481
+ /* @__PURE__ */ h("span", { style: { display: i != null && i.length ? "none" : "inline" }, className: "cosmic-ai-input-selectPlaceholder", contentEditable: !1, children: t.placeholder })
482
+ ]
483
+ },
484
+ t.id
485
+ )
486
+ );
487
+ } else t.type === "date-picker" && n.push(
488
+ /* @__PURE__ */ q(
489
+ "span",
490
+ {
491
+ id: t.id,
492
+ "data-set-type": "date-picker",
493
+ contentEditable: !0,
494
+ suppressContentEditableWarning: !0,
495
+ onClick: (i) => Oe(t, i),
496
+ "data-cosmic-ai-input-placeholder": t.placeholder,
497
+ children: [
498
+ /* @__PURE__ */ h("span", { style: { display: (g = t.content) != null && g.length ? "inline" : "none" }, contentEditable: !1, children: t.content }),
499
+ /* @__PURE__ */ h("span", { style: { display: (l = t.content) != null && l.length ? "none" : "inline" }, className: "cosmic-ai-input-datePickerPlaceholder", contentEditable: !1, children: t.placeholder })
500
+ ]
501
+ },
502
+ t.id
503
+ )
504
+ );
505
+ }), n;
506
+ };
507
+ return Ve(r, () => ({
508
+ getCurrentValue: V
509
+ })), /* @__PURE__ */ q(Be, { children: [
510
+ /* @__PURE__ */ h(
511
+ "div",
512
+ {
513
+ "data-set-type": "container",
514
+ "data-cosmic-ai-input-placeholder": k,
515
+ className: He("cosmic-ai-input", `cosmic-ai-input-rows${E}`, { "is-disabled": N }, { "is-empty": I.length === 0 || ye === "<br>" }),
516
+ ref: B,
517
+ contentEditable: !0,
518
+ suppressContentEditableWarning: !0,
519
+ onClick: (e) => we(e),
520
+ onFocus: (e) => {
521
+ w == null || w(e);
522
+ },
523
+ onBlur: (e) => {
524
+ x == null || x(e);
525
+ },
526
+ onMouseDown: (e) => Ce(e),
527
+ onKeyDown: (e) => ke(e),
528
+ onKeyUp: (e) => Re(e),
529
+ onInput: (e) => me(e),
530
+ children: $e()
531
+ }
532
+ ),
533
+ j && qe(
534
+ (P == null ? void 0 : P.type) === "multiple-select" ? /* @__PURE__ */ h(
535
+ fe,
536
+ {
537
+ ref: T,
538
+ options: te,
539
+ value: G,
540
+ position: U,
541
+ height: ce,
542
+ onChange: Q
543
+ },
544
+ "multiple-select"
545
+ ) : (P == null ? void 0 : P.type) === "date-picker" ? /* @__PURE__ */ h(
546
+ he,
547
+ {
548
+ ref: T,
549
+ value: G,
550
+ position: U,
551
+ onChange: Q
552
+ },
553
+ "date-picker"
554
+ ) : /* @__PURE__ */ h(
555
+ ge,
556
+ {
557
+ ref: T,
558
+ options: te,
559
+ value: G,
560
+ position: U,
561
+ height: ce,
562
+ onChange: Q
563
+ },
564
+ "select"
565
+ ),
566
+ document.body
567
+ )
568
+ ] });
569
+ });
570
+ Ue.displayName = "AiInput";
571
+ export {
572
+ Ue as default
573
+ };
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .cosmic-ai-input{font-size:14px;outline:none}.cosmic-ai-input [data-set-type=input]{color:#b4c5fc;padding:0 2px;caret-color:#000}.cosmic-ai-input [data-set-type=select]{padding:0 2px;outline:none;color:#2356f6;cursor:pointer;position:relative;display:inline-block}.cosmic-ai-input [data-set-type=select] span{outline:none;background-color:#f2f5fe;border-radius:2px;white-space:nowrap;padding:0 16px 0 4px;display:inline-block}.cosmic-ai-input [data-set-type=select]:after{content:"";position:absolute;right:6px;top:50%;transform:translateY(-50%);width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #2356f6;pointer-events:none}.cosmic-ai-input [data-set-type=multiple-select]{padding:0 2px;outline:none;color:#2356f6;cursor:pointer;position:relative;display:inline-block}.cosmic-ai-input [data-set-type=multiple-select] span{outline:none;background-color:#f2f5fe;border-radius:2px;white-space:nowrap;padding:2px 16px 2px 4px;display:inline-block}.cosmic-ai-input [data-set-type=multiple-select]:after{content:"";position:absolute;right:6px;top:50%;transform:translateY(-50%);width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #2356f6;pointer-events:none}.cosmic-ai-input [data-set-type=date-picker]{padding:0 2px;outline:none;color:#2356f6;cursor:pointer;position:relative;display:inline-block}.cosmic-ai-input [data-set-type=date-picker] span{outline:none;background-color:#f2f5fe;border-radius:2px;white-space:nowrap;padding:2px 16px 2px 4px;display:inline-block}.cosmic-ai-input [data-set-type=date-picker]:after{content:"";position:absolute;right:6px;top:50%;transform:translateY(-50%);width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #2356f6;pointer-events:none}.cosmic-ai-input.is-empty:before{content:attr(data-cosmic-ai-input-placeholder);position:absolute;color:#999;pointer-events:none}.cosmic-ai-input.is-disabled{opacity:.5;pointer-events:none;cursor:not-allowed}.cosmic-ai-input-displayNone{display:none}.cosmic-ai-input-inputContent{outline:none;color:#2356f6;background-color:#f2f5fe;border-radius:2px}.cosmic-ai-input-placeholder{background-color:#f2f5fe;padding:2px 4px 2px 0;border-top-right-radius:2px;border-bottom-right-radius:2px}.cosmic-ai-input-selectPlaceholder,.cosmic-ai-input-datePickerPlaceholder{color:#b4c5fc}.cosmic-ai-input-rows1{min-height:auto}.cosmic-ai-input-rows2{min-height:46px}.cosmic-ai-input-rows3{min-height:69px}.cosmic-ai-input-rows4{min-height:92px}.cosmic-ai-input-selectFloatElement{background-color:#fff;border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 2px 8px #00000026;overflow-y:auto;z-index:5000;max-width:240px}.cosmic-ai-input-selectFloatElement .selectOption{padding:8px 12px;cursor:pointer;transition:background-color .2s ease;border-bottom:1px solid #f0f0f0;font-size:14px;color:#333;box-sizing:border-box;word-wrap:break-word;word-break:break-all;display:flex;align-items:center;justify-content:space-between}.cosmic-ai-input-selectFloatElement .selectOption:last-child{border-bottom:none}.cosmic-ai-input-selectFloatElement .selectOption:hover{background-color:#f5f5f5}.cosmic-ai-input-selectFloatElement .selectOption.selected{background-color:#e6f0ff;color:#2356f6;font-weight:500}.cosmic-ai-input-selectFloatElement .selectOption.selected:after{content:"✓";color:#2356f6;padding-left:6px}.cosmic-ai-input-datePicker{position:absolute;z-index:5000}.cosmic-ai-input-datePicker input[type=date]{visibility:hidden;height:0!important;box-sizing:border-box;border:none!important;position:relative;top:-10px}.cosmic-ai-input-commonSlot{padding:2px 0}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "cosmic-ai-input",
3
+ "version": "1.0.0",
4
+ "description": "A powerful AI conversation input component for React with TypeScript support",
5
+ "main": "./dist/index.cjs.js",
6
+ "module": "./dist/index.es.js",
7
+ "types": "./dist/index.d.ts",
8
+ "private": false,
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.es.js",
12
+ "require": "./dist/index.cjs.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./dist/style.css": "./dist/style.css",
16
+ "./style.css": "./dist/style-global.css",
17
+ "./styles.css": "./dist/style-global.css",
18
+ "./styles": "./styles.js",
19
+ "./styles.cjs": "./styles.cjs",
20
+ "./package.json": "./package.json"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "styles.js",
25
+ "styles.cjs",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "scripts": {
30
+ "dev": "vite",
31
+ "build": "vite build",
32
+ "test": "echo \"Error: no test specified\" && exit 1",
33
+ "prepublishOnly": "npm run build"
34
+ },
35
+ "keywords": [
36
+ "react",
37
+ "ai",
38
+ "input",
39
+ "conversation",
40
+ "typescript"
41
+ ],
42
+ "author": "",
43
+ "license": "ISC",
44
+ "peerDependencies": {
45
+ "classnames": "^2.5.1",
46
+ "react": "^18.2.0",
47
+ "react-dom": "^18.2.0"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "react": {
51
+ "optional": false
52
+ },
53
+ "react-dom": {
54
+ "optional": false
55
+ },
56
+ "classnames": {
57
+ "optional": false
58
+ }
59
+ },
60
+ "dependencies": {
61
+ "core-js": "^3.47.0"
62
+ },
63
+ "devDependencies": {
64
+ "@babel/preset-env": "^7.28.5",
65
+ "@types/react": "^18.3.12",
66
+ "@types/react-dom": "^18.3.1",
67
+ "@vitejs/plugin-react": "^4.3.1",
68
+ "classnames": "^2.5.1",
69
+ "less": "^4.2.0",
70
+ "react": "^18.2.0",
71
+ "react-dom": "^18.2.0",
72
+ "typescript": "^5.6.3",
73
+ "vite": "^5.4.11",
74
+ "vite-plugin-dts": "^4.5.4"
75
+ },
76
+ "bundledDependencies": [],
77
+ "bundleDependencies": []
78
+ }