prompt-area 0.1.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/README.md +11 -3
- package/dist/action-bar/index.js +1 -4
- package/dist/chat-prompt-layout/index.js +1 -4
- package/dist/chunk-23Y7B365.js +2 -0
- package/dist/chunk-2R57LWJO.js +3 -0
- package/dist/chunk-3D4ZBBYY.js +2 -0
- package/dist/chunk-6VISE4VA.js +2 -0
- package/dist/chunk-A6EFF4BI.js +1 -0
- package/dist/chunk-CRC4ST6U.js +3 -0
- package/dist/chunk-LJJ6HHR6.js +14 -0
- package/dist/chunk-MJSTEY4N.js +7 -0
- package/dist/chunk-VULUMPYE.js +2 -0
- package/dist/compact-prompt-area/index.js +1 -5
- package/dist/helpers/index.d.ts +3 -185
- package/dist/helpers/index.js +1 -291
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -9
- package/dist/prompt-area/index.d.ts +4 -191
- package/dist/prompt-area/index.js +1 -5
- package/dist/status-bar/index.js +1 -4
- package/package.json +25 -13
- package/LICENSE +0 -21
- package/dist/action-bar/index.js.map +0 -1
- package/dist/chat-prompt-layout/index.js.map +0 -1
- package/dist/chunk-ANZZEZP2.js +0 -38
- package/dist/chunk-ANZZEZP2.js.map +0 -1
- package/dist/chunk-BPJO4DGM.js +0 -198
- package/dist/chunk-BPJO4DGM.js.map +0 -1
- package/dist/chunk-BWVBDP7C.js +0 -38
- package/dist/chunk-BWVBDP7C.js.map +0 -1
- package/dist/chunk-E7HUXORB.js +0 -2692
- package/dist/chunk-E7HUXORB.js.map +0 -1
- package/dist/chunk-NF2LHZIE.js +0 -12
- package/dist/chunk-NF2LHZIE.js.map +0 -1
- package/dist/chunk-UBBCAMJA.js +0 -116
- package/dist/chunk-UBBCAMJA.js.map +0 -1
- package/dist/chunk-XDKRP7UE.js +0 -125
- package/dist/chunk-XDKRP7UE.js.map +0 -1
- package/dist/compact-prompt-area/index.js.map +0 -1
- package/dist/helpers/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/prompt-area/index.js.map +0 -1
- package/dist/status-bar/index.js.map +0 -1
package/dist/helpers/index.js
CHANGED
|
@@ -1,291 +1 @@
|
|
|
1
|
-
|
|
2
|
-
function segmentsToPlainText(segments) {
|
|
3
|
-
return segments.map((seg) => {
|
|
4
|
-
if (seg.type === "text") return seg.text;
|
|
5
|
-
return `${seg.trigger}${seg.displayText}`;
|
|
6
|
-
}).join("");
|
|
7
|
-
}
|
|
8
|
-
function plainTextToSegments(text2) {
|
|
9
|
-
if (!text2) return [];
|
|
10
|
-
return [{ type: "text", text: text2 }];
|
|
11
|
-
}
|
|
12
|
-
function isValidTriggerPosition(text2, charIndex, position) {
|
|
13
|
-
if (charIndex === 0) return true;
|
|
14
|
-
const prevChar = text2[charIndex - 1];
|
|
15
|
-
if (position === "start") {
|
|
16
|
-
return prevChar === "\n";
|
|
17
|
-
}
|
|
18
|
-
return prevChar === " " || prevChar === "\n" || prevChar === " ";
|
|
19
|
-
}
|
|
20
|
-
function detectActiveTrigger(text2, cursorPos, triggers) {
|
|
21
|
-
if (!text2 || cursorPos === 0 || triggers.length === 0) return null;
|
|
22
|
-
for (let i = cursorPos - 1; i >= 0; i--) {
|
|
23
|
-
const char = text2[i];
|
|
24
|
-
if (char === " " || char === "\n" || char === " ") {
|
|
25
|
-
if (i + 1 < cursorPos) {
|
|
26
|
-
const nextChar = text2[i + 1];
|
|
27
|
-
const matchingTrigger2 = triggers.find((t) => t.char === nextChar);
|
|
28
|
-
if (matchingTrigger2 && isValidTriggerPosition(text2, i + 1, matchingTrigger2.position)) {
|
|
29
|
-
return {
|
|
30
|
-
config: matchingTrigger2,
|
|
31
|
-
startOffset: i + 1,
|
|
32
|
-
query: text2.slice(i + 2, cursorPos)
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
const matchingTrigger = triggers.find((t) => t.char === char);
|
|
39
|
-
if (matchingTrigger && isValidTriggerPosition(text2, i, matchingTrigger.position)) {
|
|
40
|
-
return {
|
|
41
|
-
config: matchingTrigger,
|
|
42
|
-
startOffset: i,
|
|
43
|
-
query: text2.slice(i + 1, cursorPos)
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
function resolveChip(segments, activeTrigger, chip2) {
|
|
50
|
-
const triggerStart = activeTrigger.startOffset;
|
|
51
|
-
const triggerEnd = triggerStart + 1 + activeTrigger.query.length;
|
|
52
|
-
const newSegments = [];
|
|
53
|
-
let offset = 0;
|
|
54
|
-
for (const seg of segments) {
|
|
55
|
-
if (seg.type === "chip") {
|
|
56
|
-
const chipText = `${seg.trigger}${seg.displayText}`;
|
|
57
|
-
const chipStart = offset;
|
|
58
|
-
const chipEnd = offset + chipText.length;
|
|
59
|
-
if (chipEnd <= triggerStart || chipStart >= triggerEnd) {
|
|
60
|
-
newSegments.push(seg);
|
|
61
|
-
}
|
|
62
|
-
offset = chipEnd;
|
|
63
|
-
} else {
|
|
64
|
-
const textStart = offset;
|
|
65
|
-
const textEnd = offset + seg.text.length;
|
|
66
|
-
if (textEnd <= triggerStart) {
|
|
67
|
-
newSegments.push(seg);
|
|
68
|
-
} else if (textStart >= triggerEnd) {
|
|
69
|
-
newSegments.push(seg);
|
|
70
|
-
} else {
|
|
71
|
-
const beforeText = seg.text.slice(0, Math.max(0, triggerStart - textStart));
|
|
72
|
-
const afterText = seg.text.slice(Math.min(seg.text.length, triggerEnd - textStart));
|
|
73
|
-
if (beforeText) {
|
|
74
|
-
newSegments.push({ type: "text", text: beforeText });
|
|
75
|
-
}
|
|
76
|
-
const newChip = {
|
|
77
|
-
type: "chip",
|
|
78
|
-
trigger: activeTrigger.config.char,
|
|
79
|
-
value: chip2.value,
|
|
80
|
-
displayText: chip2.displayText,
|
|
81
|
-
...chip2.data !== void 0 ? { data: chip2.data } : {},
|
|
82
|
-
...chip2.autoResolved ? { autoResolved: true } : {}
|
|
83
|
-
};
|
|
84
|
-
newSegments.push(newChip);
|
|
85
|
-
if (afterText) {
|
|
86
|
-
newSegments.push({ type: "text", text: " " + afterText.replace(/^\s/, "") });
|
|
87
|
-
} else {
|
|
88
|
-
newSegments.push({ type: "text", text: " " });
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
offset = textEnd;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const merged = mergeAdjacentTextSegments(newSegments);
|
|
95
|
-
let lastChipEndOffset = -1;
|
|
96
|
-
let runningOffset = 0;
|
|
97
|
-
for (const seg of merged) {
|
|
98
|
-
if (seg.type === "text") {
|
|
99
|
-
runningOffset += seg.text.length;
|
|
100
|
-
} else {
|
|
101
|
-
runningOffset += seg.trigger.length + seg.displayText.length;
|
|
102
|
-
if (seg.value === chip2.value && seg.displayText === chip2.displayText && seg.trigger === activeTrigger.config.char) {
|
|
103
|
-
lastChipEndOffset = runningOffset;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const cursorOffset = lastChipEndOffset === -1 ? runningOffset : lastChipEndOffset + 1;
|
|
108
|
-
return { segments: merged, cursorOffset };
|
|
109
|
-
}
|
|
110
|
-
function resolveTriggersInSegments(segments, triggers) {
|
|
111
|
-
const autoResolveTriggers = triggers.filter((t) => t.resolveOnSpace);
|
|
112
|
-
if (autoResolveTriggers.length === 0) return segments;
|
|
113
|
-
const triggerChars = new Set(autoResolveTriggers.map((t) => t.char));
|
|
114
|
-
const result = [];
|
|
115
|
-
for (const seg of segments) {
|
|
116
|
-
if (seg.type === "chip") {
|
|
117
|
-
result.push(seg);
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
const parts = splitTextByTriggerPatterns(seg.text, autoResolveTriggers, triggerChars);
|
|
121
|
-
result.push(...parts);
|
|
122
|
-
}
|
|
123
|
-
return mergeAdjacentTextSegments(result);
|
|
124
|
-
}
|
|
125
|
-
function splitTextByTriggerPatterns(text2, triggers, triggerChars) {
|
|
126
|
-
if (!text2) return [];
|
|
127
|
-
const segments = [];
|
|
128
|
-
let i = 0;
|
|
129
|
-
while (i < text2.length) {
|
|
130
|
-
const char = text2[i];
|
|
131
|
-
if (triggerChars.has(char)) {
|
|
132
|
-
const isAtBoundary = i === 0 || text2[i - 1] === " " || text2[i - 1] === "\n" || text2[i - 1] === " ";
|
|
133
|
-
if (isAtBoundary) {
|
|
134
|
-
const trigger = triggers.find((t) => t.char === char);
|
|
135
|
-
if (trigger && isValidTriggerPosition(text2, i, trigger.position)) {
|
|
136
|
-
let end = i + 1;
|
|
137
|
-
while (end < text2.length && text2[end] !== " " && text2[end] !== "\n" && text2[end] !== " ") {
|
|
138
|
-
end++;
|
|
139
|
-
}
|
|
140
|
-
const query = text2.slice(i + 1, end);
|
|
141
|
-
if (query.length > 0) {
|
|
142
|
-
const displayText = trigger.onSelect?.({ value: query, label: query }) || query;
|
|
143
|
-
segments.push({
|
|
144
|
-
type: "chip",
|
|
145
|
-
trigger: char,
|
|
146
|
-
value: query,
|
|
147
|
-
displayText,
|
|
148
|
-
autoResolved: true
|
|
149
|
-
});
|
|
150
|
-
i = end;
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const start = i;
|
|
157
|
-
i++;
|
|
158
|
-
while (i < text2.length && !(triggerChars.has(text2[i]) && (text2[i - 1] === " " || text2[i - 1] === "\n" || text2[i - 1] === " "))) {
|
|
159
|
-
i++;
|
|
160
|
-
}
|
|
161
|
-
segments.push({ type: "text", text: text2.slice(start, i) });
|
|
162
|
-
}
|
|
163
|
-
return segments;
|
|
164
|
-
}
|
|
165
|
-
function parseInlineMarkdown(text2) {
|
|
166
|
-
if (!text2) return [];
|
|
167
|
-
const tokens = [];
|
|
168
|
-
const pattern = /(\*{3}(.+?)\*{3})|(\*{2}(.+?)\*{2})|(\*(.+?)\*)|(https?:\/\/[^\s),]+)/g;
|
|
169
|
-
let lastIndex = 0;
|
|
170
|
-
let match;
|
|
171
|
-
while ((match = pattern.exec(text2)) !== null) {
|
|
172
|
-
if (match.index > lastIndex) {
|
|
173
|
-
tokens.push({ type: "plain", text: text2.slice(lastIndex, match.index) });
|
|
174
|
-
}
|
|
175
|
-
if (match[1] && match[2]) {
|
|
176
|
-
tokens.push({ type: "bold-italic", text: match[2] });
|
|
177
|
-
} else if (match[3] && match[4]) {
|
|
178
|
-
tokens.push({ type: "bold", text: match[4] });
|
|
179
|
-
} else if (match[5] && match[6]) {
|
|
180
|
-
tokens.push({ type: "italic", text: match[6] });
|
|
181
|
-
} else if (match[7]) {
|
|
182
|
-
tokens.push({ type: "url", text: match[7] });
|
|
183
|
-
}
|
|
184
|
-
lastIndex = match.index + match[0].length;
|
|
185
|
-
}
|
|
186
|
-
if (lastIndex < text2.length) {
|
|
187
|
-
tokens.push({ type: "plain", text: text2.slice(lastIndex) });
|
|
188
|
-
}
|
|
189
|
-
return tokens;
|
|
190
|
-
}
|
|
191
|
-
function segmentsEqual(a, b) {
|
|
192
|
-
if (a === b) return true;
|
|
193
|
-
if (a.length !== b.length) return false;
|
|
194
|
-
for (let i = 0; i < a.length; i++) {
|
|
195
|
-
const sa = a[i];
|
|
196
|
-
const sb = b[i];
|
|
197
|
-
if (sa.type !== sb.type) return false;
|
|
198
|
-
if (sa.type === "text") {
|
|
199
|
-
if (sb.type !== "text" || sa.text !== sb.text) return false;
|
|
200
|
-
} else {
|
|
201
|
-
if (sb.type !== "chip" || sa.trigger !== sb.trigger || sa.value !== sb.value || sa.displayText !== sb.displayText || sa.autoResolved !== sb.autoResolved)
|
|
202
|
-
return false;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return true;
|
|
206
|
-
}
|
|
207
|
-
function mergeAdjacentTextSegments(segments) {
|
|
208
|
-
const result = [];
|
|
209
|
-
for (const seg of segments) {
|
|
210
|
-
if (seg.type === "text" && seg.text === "") continue;
|
|
211
|
-
const last = result[result.length - 1];
|
|
212
|
-
if (seg.type === "text" && last?.type === "text") {
|
|
213
|
-
result[result.length - 1] = { type: "text", text: last.text + seg.text };
|
|
214
|
-
} else {
|
|
215
|
-
result.push(seg);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return result;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// src/prompt-area/segment-helpers.ts
|
|
222
|
-
function text(value) {
|
|
223
|
-
return { type: "text", text: value };
|
|
224
|
-
}
|
|
225
|
-
function chip(opts) {
|
|
226
|
-
return { type: "chip", ...opts };
|
|
227
|
-
}
|
|
228
|
-
function isSegmentsEmpty(segments) {
|
|
229
|
-
if (segments.length === 0) return true;
|
|
230
|
-
return segments.every((seg) => seg.type === "text" && seg.text.trim() === "");
|
|
231
|
-
}
|
|
232
|
-
function hasChips(segments) {
|
|
233
|
-
return segments.some((seg) => seg.type === "chip");
|
|
234
|
-
}
|
|
235
|
-
function getChips(segments) {
|
|
236
|
-
return segments.filter((seg) => seg.type === "chip");
|
|
237
|
-
}
|
|
238
|
-
function getChipsByTrigger(segments, trigger) {
|
|
239
|
-
return segments.filter(
|
|
240
|
-
(seg) => seg.type === "chip" && seg.trigger === trigger
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// src/prompt-area/trigger-presets.ts
|
|
245
|
-
function mentionTrigger(opts = {}) {
|
|
246
|
-
const { char = "@", ...rest } = opts;
|
|
247
|
-
return {
|
|
248
|
-
char,
|
|
249
|
-
position: "any",
|
|
250
|
-
mode: "dropdown",
|
|
251
|
-
chipStyle: "pill",
|
|
252
|
-
accessibilityLabel: "mention",
|
|
253
|
-
...rest
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
function commandTrigger(opts = {}) {
|
|
257
|
-
const { char = "/", ...rest } = opts;
|
|
258
|
-
return {
|
|
259
|
-
char,
|
|
260
|
-
position: "start",
|
|
261
|
-
mode: "dropdown",
|
|
262
|
-
chipStyle: "inline",
|
|
263
|
-
accessibilityLabel: "command",
|
|
264
|
-
...rest
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
function hashtagTrigger(opts = {}) {
|
|
268
|
-
const { char = "#", ...rest } = opts;
|
|
269
|
-
return {
|
|
270
|
-
char,
|
|
271
|
-
position: "any",
|
|
272
|
-
mode: "dropdown",
|
|
273
|
-
chipStyle: "pill",
|
|
274
|
-
resolveOnSpace: true,
|
|
275
|
-
accessibilityLabel: "tag",
|
|
276
|
-
...rest
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
function callbackTrigger(opts) {
|
|
280
|
-
const { char, ...rest } = opts;
|
|
281
|
-
return {
|
|
282
|
-
char,
|
|
283
|
-
position: "start",
|
|
284
|
-
mode: "callback",
|
|
285
|
-
...rest
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export { callbackTrigger, chip, commandTrigger, detectActiveTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, isValidTriggerPosition, mentionTrigger, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, text };
|
|
290
|
-
//# sourceMappingURL=index.js.map
|
|
291
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export{j as callbackTrigger,b as chip,h as commandTrigger,e as getChips,f as getChipsByTrigger,d as hasChips,i as hashtagTrigger,c as isSegmentsEmpty,g as mentionTrigger,a as text}from'../chunk-A6EFF4BI.js';export{d as detectActiveTrigger,c as isValidTriggerPosition,m as mergeAdjacentTextSegments,k as parseInlineMarkdown,b as plainTextToSegments,e as resolveChip,h as resolveTriggersInSegments,l as segmentsEqual,a as segmentsToPlainText}from'../chunk-MJSTEY4N.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { PromptArea, PromptAreaBind, PromptAreaState, UsePromptAreaStateOptions, usePromptArea, usePromptAreaState } from './prompt-area/index.js';
|
|
2
2
|
export { A as ActiveTrigger, C as ChipSegment, a as ChipStyle, P as PromptAreaFile, b as PromptAreaHandle, c as PromptAreaImage, d as PromptAreaProps, S as Segment, T as TextSegment, e as TriggerActivateContext, f as TriggerConfig, g as TriggerMode, h as TriggerPosition, i as TriggerSuggestion } from './types-C4BgDEpe.js';
|
|
3
|
+
export { CallbackTriggerOptions, CommandTriggerOptions, HashtagTriggerOptions, MarkdownToken, MentionTriggerOptions, callbackTrigger, chip, commandTrigger, detectActiveTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, isValidTriggerPosition, mentionTrigger, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, text } from './helpers/index.js';
|
|
3
4
|
export { ActionBar, ActionBarProps } from './action-bar/index.js';
|
|
4
5
|
export { StatusBar, StatusBarProps } from './status-bar/index.js';
|
|
5
6
|
export { CompactPromptArea, CompactPromptAreaProps } from './compact-prompt-area/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { callbackTrigger, chip, commandTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, mentionTrigger, text,
|
|
3
|
-
export { ActionBar } from './chunk-BWVBDP7C.js';
|
|
4
|
-
export { StatusBar } from './chunk-ANZZEZP2.js';
|
|
5
|
-
export { CompactPromptArea } from './chunk-BPJO4DGM.js';
|
|
6
|
-
export { PromptArea, detectActiveTrigger, isValidTriggerPosition, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, usePromptArea } from './chunk-E7HUXORB.js';
|
|
7
|
-
export { ChatPromptLayout } from './chunk-XDKRP7UE.js';
|
|
8
|
-
import './chunk-NF2LHZIE.js';
|
|
9
|
-
//# sourceMappingURL=index.js.map
|
|
10
|
-
//# sourceMappingURL=index.js.map
|
|
2
|
+
export{a as usePromptAreaState}from'./chunk-3D4ZBBYY.js';export{a as ActionBar}from'./chunk-VULUMPYE.js';export{a as StatusBar}from'./chunk-6VISE4VA.js';export{a as CompactPromptArea}from'./chunk-2R57LWJO.js';export{c as PromptArea,b as usePromptArea}from'./chunk-LJJ6HHR6.js';export{a as ChatPromptLayout}from'./chunk-CRC4ST6U.js';import'./chunk-23Y7B365.js';export{j as callbackTrigger,b as chip,h as commandTrigger,e as getChips,f as getChipsByTrigger,d as hasChips,i as hashtagTrigger,c as isSegmentsEmpty,g as mentionTrigger,a as text}from'./chunk-A6EFF4BI.js';export{d as detectActiveTrigger,c as isValidTriggerPosition,m as mergeAdjacentTextSegments,k as parseInlineMarkdown,b as plainTextToSegments,e as resolveChip,h as resolveTriggersInSegments,l as segmentsEqual,a as segmentsToPlainText}from'./chunk-MJSTEY4N.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { d as PromptAreaProps, b as PromptAreaHandle, S as Segment, f as TriggerConfig, C as ChipSegment, A as ActiveTrigger, i as TriggerSuggestion
|
|
3
|
-
export { a as ChipStyle, P as PromptAreaFile, c as PromptAreaImage, e as TriggerActivateContext, g as TriggerMode } from '../types-C4BgDEpe.js';
|
|
2
|
+
import { d as PromptAreaProps, b as PromptAreaHandle, S as Segment, f as TriggerConfig, C as ChipSegment, A as ActiveTrigger, i as TriggerSuggestion } from '../types-C4BgDEpe.js';
|
|
3
|
+
export { a as ChipStyle, P as PromptAreaFile, c as PromptAreaImage, T as TextSegment, e as TriggerActivateContext, g as TriggerMode, h as TriggerPosition } from '../types-C4BgDEpe.js';
|
|
4
|
+
export { CallbackTriggerOptions, CommandTriggerOptions, HashtagTriggerOptions, MarkdownToken, MentionTriggerOptions, callbackTrigger, chip, commandTrigger, detectActiveTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, isValidTriggerPosition, mentionTrigger, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, text } from '../helpers/index.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* PromptArea - A lightweight rich text input with trigger support.
|
|
@@ -136,192 +137,4 @@ type PromptAreaState = {
|
|
|
136
137
|
};
|
|
137
138
|
declare function usePromptAreaState(options?: UsePromptAreaStateOptions): PromptAreaState;
|
|
138
139
|
|
|
139
|
-
|
|
140
|
-
* Pure logic engine for the PromptArea component.
|
|
141
|
-
* No DOM dependencies - fully testable in Node.
|
|
142
|
-
*/
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Converts an array of segments to a plain text string.
|
|
146
|
-
* Chips are represented as `{trigger}{displayText}` (e.g., "@Alice").
|
|
147
|
-
*/
|
|
148
|
-
declare function segmentsToPlainText(segments: Segment[]): string;
|
|
149
|
-
/**
|
|
150
|
-
* Converts plain text into a single text segment.
|
|
151
|
-
* Used for initial value conversion from plain strings.
|
|
152
|
-
*/
|
|
153
|
-
declare function plainTextToSegments(text: string): Segment[];
|
|
154
|
-
/**
|
|
155
|
-
* Checks whether a trigger character at the given position in text
|
|
156
|
-
* is valid according to the position rule.
|
|
157
|
-
*
|
|
158
|
-
* @param text - The full text content
|
|
159
|
-
* @param charIndex - The index of the trigger character in the text
|
|
160
|
-
* @param position - The position rule to validate against
|
|
161
|
-
*/
|
|
162
|
-
declare function isValidTriggerPosition(text: string, charIndex: number, position: TriggerPosition): boolean;
|
|
163
|
-
/**
|
|
164
|
-
* Scans backwards from the cursor position to detect if the user is
|
|
165
|
-
* currently typing a trigger word.
|
|
166
|
-
*
|
|
167
|
-
* Returns the active trigger info, or null if no trigger is active.
|
|
168
|
-
*
|
|
169
|
-
* @param text - The full plain text content
|
|
170
|
-
* @param cursorPos - The cursor position (character offset from start)
|
|
171
|
-
* @param triggers - Available trigger configurations
|
|
172
|
-
*/
|
|
173
|
-
declare function detectActiveTrigger(text: string, cursorPos: number, triggers: TriggerConfig[]): ActiveTrigger | null;
|
|
174
|
-
/**
|
|
175
|
-
* Resolves an active trigger into a chip within the segments array.
|
|
176
|
-
* Replaces the trigger text (trigger char + query) with a chip segment.
|
|
177
|
-
*
|
|
178
|
-
* @param segments - Current document segments
|
|
179
|
-
* @param activeTrigger - The active trigger to resolve
|
|
180
|
-
* @param chip - The chip data (value, displayText, optional data)
|
|
181
|
-
* @returns New segments array with the chip inserted, and the new cursor position
|
|
182
|
-
*/
|
|
183
|
-
declare function resolveChip(segments: Segment[], activeTrigger: ActiveTrigger, chip: {
|
|
184
|
-
value: string;
|
|
185
|
-
displayText: string;
|
|
186
|
-
data?: unknown;
|
|
187
|
-
autoResolved?: boolean;
|
|
188
|
-
}): {
|
|
189
|
-
segments: Segment[];
|
|
190
|
-
cursorOffset: number;
|
|
191
|
-
};
|
|
192
|
-
/**
|
|
193
|
-
* Scans text segments for trigger patterns and auto-resolves them into chips.
|
|
194
|
-
* Only resolves triggers that have `resolveOnSpace: true`.
|
|
195
|
-
*
|
|
196
|
-
* Trigger patterns must appear at word boundaries: start of text, after
|
|
197
|
-
* whitespace, or after a newline. This avoids false positives like email
|
|
198
|
-
* addresses (user@example.com).
|
|
199
|
-
*/
|
|
200
|
-
declare function resolveTriggersInSegments(segments: Segment[], triggers: TriggerConfig[]): Segment[];
|
|
201
|
-
type MarkdownToken = {
|
|
202
|
-
type: 'plain';
|
|
203
|
-
text: string;
|
|
204
|
-
} | {
|
|
205
|
-
type: 'bold';
|
|
206
|
-
text: string;
|
|
207
|
-
} | {
|
|
208
|
-
type: 'italic';
|
|
209
|
-
text: string;
|
|
210
|
-
} | {
|
|
211
|
-
type: 'bold-italic';
|
|
212
|
-
text: string;
|
|
213
|
-
} | {
|
|
214
|
-
type: 'url';
|
|
215
|
-
text: string;
|
|
216
|
-
};
|
|
217
|
-
/**
|
|
218
|
-
* Parses text for simple inline markdown: bold, italic, bold-italic, and URLs.
|
|
219
|
-
* Does NOT handle block-level markdown (lists, headings, etc.).
|
|
220
|
-
*/
|
|
221
|
-
declare function parseInlineMarkdown(text: string): MarkdownToken[];
|
|
222
|
-
/**
|
|
223
|
-
* Shallow equality check for two segment arrays.
|
|
224
|
-
* Compares type, text, trigger, value, displayText, and autoResolved fields.
|
|
225
|
-
* Avoids JSON.stringify overhead for the common case.
|
|
226
|
-
*/
|
|
227
|
-
declare function segmentsEqual(a: Segment[], b: Segment[]): boolean;
|
|
228
|
-
/**
|
|
229
|
-
* Merges adjacent text segments into single text segments.
|
|
230
|
-
* Also removes empty text segments.
|
|
231
|
-
*/
|
|
232
|
-
declare function mergeAdjacentTextSegments(segments: Segment[]): Segment[];
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Convenience helpers for creating and inspecting Segments.
|
|
236
|
-
*
|
|
237
|
-
* These reduce boilerplate when building AI chat UIs that work with the
|
|
238
|
-
* PromptArea document model.
|
|
239
|
-
*
|
|
240
|
-
* @example
|
|
241
|
-
* ```ts
|
|
242
|
-
* import { text, chip, isSegmentsEmpty, segmentsToPlainText } from './segment-helpers'
|
|
243
|
-
*
|
|
244
|
-
* const greeting = [text('Hello '), chip({ trigger: '@', value: 'u1', displayText: 'Alice' })]
|
|
245
|
-
* isSegmentsEmpty(greeting) // false
|
|
246
|
-
* segmentsToPlainText(greeting) // "Hello @Alice"
|
|
247
|
-
* ```
|
|
248
|
-
*/
|
|
249
|
-
|
|
250
|
-
/** Create a text segment. */
|
|
251
|
-
declare function text(value: string): TextSegment;
|
|
252
|
-
/** Create a chip segment. */
|
|
253
|
-
declare function chip(opts: Omit<ChipSegment, 'type'>): ChipSegment;
|
|
254
|
-
/** Returns `true` when the segment array is empty or contains only whitespace text. */
|
|
255
|
-
declare function isSegmentsEmpty(segments: Segment[]): boolean;
|
|
256
|
-
/** Returns `true` when the segment array contains at least one chip. */
|
|
257
|
-
declare function hasChips(segments: Segment[]): boolean;
|
|
258
|
-
/** Extracts all chip segments from a segment array. */
|
|
259
|
-
declare function getChips(segments: Segment[]): ChipSegment[];
|
|
260
|
-
/** Extracts chips matching a specific trigger character. */
|
|
261
|
-
declare function getChipsByTrigger(segments: Segment[], trigger: string): ChipSegment[];
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Pre-built trigger configuration factories for common AI chat patterns.
|
|
265
|
-
*
|
|
266
|
-
* Each factory returns a full `TriggerConfig` with sensible defaults.
|
|
267
|
-
* Pass only what you need to override.
|
|
268
|
-
*
|
|
269
|
-
* @example
|
|
270
|
-
* ```tsx
|
|
271
|
-
* <PromptArea
|
|
272
|
-
* triggers={[
|
|
273
|
-
* mentionTrigger({ onSearch: searchUsers }),
|
|
274
|
-
* commandTrigger({ onSearch: searchCommands }),
|
|
275
|
-
* hashtagTrigger(),
|
|
276
|
-
* ]}
|
|
277
|
-
* />
|
|
278
|
-
* ```
|
|
279
|
-
*/
|
|
280
|
-
|
|
281
|
-
type TriggerPresetOptions = Omit<Partial<TriggerConfig>, 'char' | 'position' | 'mode'>;
|
|
282
|
-
type MentionTriggerOptions = TriggerPresetOptions & {
|
|
283
|
-
/** Override the trigger character. Defaults to `'@'`. */
|
|
284
|
-
char?: string;
|
|
285
|
-
};
|
|
286
|
-
/**
|
|
287
|
-
* Creates a **mention** trigger (`@`).
|
|
288
|
-
*
|
|
289
|
-
* Defaults: `position: 'any'`, `mode: 'dropdown'`, `chipStyle: 'pill'`,
|
|
290
|
-
* accessible label `"mention"`.
|
|
291
|
-
*/
|
|
292
|
-
declare function mentionTrigger(opts?: MentionTriggerOptions): TriggerConfig;
|
|
293
|
-
type CommandTriggerOptions = TriggerPresetOptions & {
|
|
294
|
-
/** Override the trigger character. Defaults to `'/'`. */
|
|
295
|
-
char?: string;
|
|
296
|
-
};
|
|
297
|
-
/**
|
|
298
|
-
* Creates a **command** trigger (`/`).
|
|
299
|
-
*
|
|
300
|
-
* Defaults: `position: 'start'`, `mode: 'dropdown'`, `chipStyle: 'inline'`,
|
|
301
|
-
* accessible label `"command"`.
|
|
302
|
-
*/
|
|
303
|
-
declare function commandTrigger(opts?: CommandTriggerOptions): TriggerConfig;
|
|
304
|
-
type HashtagTriggerOptions = TriggerPresetOptions & {
|
|
305
|
-
/** Override the trigger character. Defaults to `'#'`. */
|
|
306
|
-
char?: string;
|
|
307
|
-
};
|
|
308
|
-
/**
|
|
309
|
-
* Creates a **hashtag / tag** trigger (`#`).
|
|
310
|
-
*
|
|
311
|
-
* Defaults: `position: 'any'`, `mode: 'dropdown'`, `chipStyle: 'pill'`,
|
|
312
|
-
* `resolveOnSpace: true`, accessible label `"tag"`.
|
|
313
|
-
*/
|
|
314
|
-
declare function hashtagTrigger(opts?: HashtagTriggerOptions): TriggerConfig;
|
|
315
|
-
type CallbackTriggerOptions = Omit<Partial<TriggerConfig>, 'mode'> & {
|
|
316
|
-
/** The trigger character. Required. */
|
|
317
|
-
char: string;
|
|
318
|
-
};
|
|
319
|
-
/**
|
|
320
|
-
* Creates a **callback** trigger that fires `onActivate` instead of showing
|
|
321
|
-
* a dropdown. Useful for opening file pickers, model selectors, etc.
|
|
322
|
-
*
|
|
323
|
-
* Defaults: `position: 'start'`, `mode: 'callback'`.
|
|
324
|
-
*/
|
|
325
|
-
declare function callbackTrigger(opts: CallbackTriggerOptions): TriggerConfig;
|
|
326
|
-
|
|
327
|
-
export { ActiveTrigger, type CallbackTriggerOptions, ChipSegment, type CommandTriggerOptions, type HashtagTriggerOptions, type MarkdownToken, type MentionTriggerOptions, PromptArea, type PromptAreaBind, PromptAreaHandle, PromptAreaProps, type PromptAreaState, Segment, TextSegment, TriggerConfig, TriggerPosition, TriggerSuggestion, type UsePromptAreaStateOptions, callbackTrigger, chip, commandTrigger, detectActiveTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, isValidTriggerPosition, mentionTrigger, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, text, usePromptArea, usePromptAreaState };
|
|
140
|
+
export { ActiveTrigger, ChipSegment, PromptArea, type PromptAreaBind, PromptAreaHandle, PromptAreaProps, type PromptAreaState, Segment, TriggerConfig, TriggerSuggestion, type UsePromptAreaStateOptions, usePromptArea, usePromptAreaState };
|
|
@@ -1,6 +1,2 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { callbackTrigger, chip, commandTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, mentionTrigger, text,
|
|
3
|
-
export { PromptArea, detectActiveTrigger, isValidTriggerPosition, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, usePromptArea } from '../chunk-E7HUXORB.js';
|
|
4
|
-
import '../chunk-NF2LHZIE.js';
|
|
5
|
-
//# sourceMappingURL=index.js.map
|
|
6
|
-
//# sourceMappingURL=index.js.map
|
|
2
|
+
export{a as usePromptAreaState}from'../chunk-3D4ZBBYY.js';export{c as PromptArea,b as usePromptArea}from'../chunk-LJJ6HHR6.js';import'../chunk-23Y7B365.js';export{j as callbackTrigger,b as chip,h as commandTrigger,e as getChips,f as getChipsByTrigger,d as hasChips,i as hashtagTrigger,c as isSegmentsEmpty,g as mentionTrigger,a as text}from'../chunk-A6EFF4BI.js';export{d as detectActiveTrigger,c as isValidTriggerPosition,m as mergeAdjacentTextSegments,k as parseInlineMarkdown,b as plainTextToSegments,e as resolveChip,h as resolveTriggersInSegments,l as segmentsEqual,a as segmentsToPlainText}from'../chunk-MJSTEY4N.js';
|
package/dist/status-bar/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prompt-area",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "An opinionated, dependency-light React rich-text prompt input with trigger-based chips (@mentions, /commands, #tags), inline markdown, undo/redo, file & image attachments, and a complete chat-input layout. Ships as an npm package or a shadcn registry.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"**/*.css"
|
|
30
30
|
],
|
|
31
31
|
"files": [
|
|
32
|
-
"dist"
|
|
32
|
+
"dist",
|
|
33
|
+
"CHANGELOG.md"
|
|
33
34
|
],
|
|
34
35
|
"exports": {
|
|
35
36
|
".": {
|
|
@@ -64,12 +65,31 @@
|
|
|
64
65
|
"./tailwind.css": "./dist/tailwind.css",
|
|
65
66
|
"./package.json": "./package.json"
|
|
66
67
|
},
|
|
68
|
+
"scripts": {
|
|
69
|
+
"build": "pnpm run clean && pnpm run build:js && pnpm run build:css",
|
|
70
|
+
"build:js": "tsup && node ./scripts/preserve-directives.mjs",
|
|
71
|
+
"build:css": "tailwindcss --input ./src/styles.css --output ./dist/styles.css --minify && node ./scripts/build-preset.mjs",
|
|
72
|
+
"clean": "rm -rf dist",
|
|
73
|
+
"typecheck": "tsc --noEmit",
|
|
74
|
+
"lint:exports": "publint && attw --pack . --profile esm-only --exclude-entrypoints styles.css tailwind.css",
|
|
75
|
+
"prepublishOnly": "pnpm run build"
|
|
76
|
+
},
|
|
67
77
|
"engines": {
|
|
68
78
|
"node": ">=18"
|
|
69
79
|
},
|
|
70
80
|
"peerDependencies": {
|
|
71
81
|
"react": ">=18",
|
|
72
|
-
"react-dom": ">=18"
|
|
82
|
+
"react-dom": ">=18",
|
|
83
|
+
"tailwindcss": ">=4",
|
|
84
|
+
"tw-animate-css": ">=1"
|
|
85
|
+
},
|
|
86
|
+
"peerDependenciesMeta": {
|
|
87
|
+
"tailwindcss": {
|
|
88
|
+
"optional": true
|
|
89
|
+
},
|
|
90
|
+
"tw-animate-css": {
|
|
91
|
+
"optional": true
|
|
92
|
+
}
|
|
73
93
|
},
|
|
74
94
|
"dependencies": {
|
|
75
95
|
"clsx": "^2.1.1",
|
|
@@ -86,17 +106,9 @@
|
|
|
86
106
|
"tailwindcss": "^4.3.0",
|
|
87
107
|
"tsup": "^8.5.0",
|
|
88
108
|
"tw-animate-css": "^1.4.0",
|
|
89
|
-
"typescript": "^
|
|
109
|
+
"typescript": "^6.0.3"
|
|
90
110
|
},
|
|
91
111
|
"publishConfig": {
|
|
92
112
|
"access": "public"
|
|
93
|
-
},
|
|
94
|
-
"scripts": {
|
|
95
|
-
"build": "pnpm run clean && pnpm run build:js && pnpm run build:css",
|
|
96
|
-
"build:js": "tsup && node ./scripts/preserve-directives.mjs",
|
|
97
|
-
"build:css": "tailwindcss --input ./src/styles.css --output ./dist/styles.css --minify && node ./scripts/build-preset.mjs",
|
|
98
|
-
"clean": "rm -rf dist",
|
|
99
|
-
"typecheck": "tsc --noEmit",
|
|
100
|
-
"lint:exports": "publint && attw --pack . --profile esm-only --exclude-entrypoints styles.css tailwind.css"
|
|
101
113
|
}
|
|
102
|
-
}
|
|
114
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Ilko Kacharov
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
package/dist/chunk-ANZZEZP2.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { cn } from './chunk-NF2LHZIE.js';
|
|
3
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
-
|
|
5
|
-
function StatusBar({
|
|
6
|
-
left,
|
|
7
|
-
right,
|
|
8
|
-
className,
|
|
9
|
-
disabled = false,
|
|
10
|
-
"aria-label": ariaLabel,
|
|
11
|
-
"data-test-id": dataTestId,
|
|
12
|
-
ref
|
|
13
|
-
}) {
|
|
14
|
-
return /* @__PURE__ */ jsxs(
|
|
15
|
-
"div",
|
|
16
|
-
{
|
|
17
|
-
ref,
|
|
18
|
-
role: "group",
|
|
19
|
-
"aria-label": ariaLabel ?? "Status bar",
|
|
20
|
-
"aria-disabled": disabled || void 0,
|
|
21
|
-
"data-test-id": dataTestId,
|
|
22
|
-
className: cn(
|
|
23
|
-
"status-bar",
|
|
24
|
-
"flex items-center justify-between gap-2 px-3 py-1.5 text-xs",
|
|
25
|
-
disabled && "pointer-events-none opacity-50",
|
|
26
|
-
className
|
|
27
|
-
),
|
|
28
|
-
children: [
|
|
29
|
-
left && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: left }),
|
|
30
|
-
right && /* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center gap-1.5", children: right })
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export { StatusBar };
|
|
37
|
-
//# sourceMappingURL=chunk-ANZZEZP2.js.map
|
|
38
|
-
//# sourceMappingURL=chunk-ANZZEZP2.js.map
|