mentionize 0.0.1 → 0.0.2
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/README.md +79 -7
- package/dist/cjs/MentionDropdown.d.ts +1 -0
- package/dist/cjs/MentionHighlighter.d.ts +1 -0
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +61 -7
- package/dist/cjs/index.js.map +6 -6
- package/dist/cjs/types.d.ts +15 -3
- package/dist/cjs/useMentionEngine.d.ts +1 -0
- package/dist/esm/MentionDropdown.d.ts +1 -0
- package/dist/esm/MentionHighlighter.d.ts +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +61 -7
- package/dist/esm/index.js.map +6 -6
- package/dist/esm/types.d.ts +15 -3
- package/dist/esm/useMentionEngine.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# Mentionize
|
|
2
2
|
|
|
3
|
-
A React library for building mention inputs with support for multiple triggers, async search, and full customization. It provides a transparent textarea overlaid on a highlighted div to display mentions, and a dropdown for suggestions. With zero dependencies.
|
|
3
|
+
A React library for building mention inputs with support for multiple triggers, async search, and full customization. It provides a transparent textarea overlaid on a highlighted div to display mentions, and a dropdown for suggestions. With zero dependencies other than React.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
+
npm install react
|
|
9
|
+
npm install react-dom
|
|
10
|
+
|
|
8
11
|
npm install mentionize
|
|
9
12
|
```
|
|
10
13
|
|
|
@@ -61,8 +64,10 @@ Defines how a trigger character activates suggestions and how mentions are seria
|
|
|
61
64
|
| `options?` | `T[]` | Static options array (client-side filtering) |
|
|
62
65
|
| `onSearch?` | `(query: string, page: number) => Promise<{ items: T[]; hasMore: boolean }>` | Async search with pagination |
|
|
63
66
|
| `renderOption?` | `(item: T, highlighted: boolean) => ReactNode` | Custom option rendering |
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
67
|
+
| `optionClassName?` | `string \| ((item: T) => string)` | CSS class for dropdown options, or a function for conditional styling per item |
|
|
68
|
+
| `renderMention?` | `(displayText: string, item?: unknown) => ReactNode` | Custom mention highlight rendering |
|
|
69
|
+
| `mentionClassName?` | `string \| ((mention: MentionItemData) => string)` | CSS class for highlighted mentions, or a function for conditional styling |
|
|
70
|
+
| `onSelect?` | `(item: T) => Promise<string \| null> \| string \| null` | Action trigger: runs instead of inserting a mention. Returns text to insert or null to cancel. |
|
|
66
71
|
|
|
67
72
|
### `MentionInputProps`
|
|
68
73
|
|
|
@@ -81,7 +86,10 @@ Defines how a trigger character activates suggestions and how mentions are seria
|
|
|
81
86
|
| `highlighterClassName?` | `string` | Highlighter overlay className |
|
|
82
87
|
| `dropdownClassName?` | `string` | Dropdown className |
|
|
83
88
|
| `dropdownWidth?` | `number` | Dropdown width in pixels (default: 250) |
|
|
89
|
+
| `loadingText?` | `string` | Text shown while loading async results (default: `"Loading..."`) |
|
|
84
90
|
| `renderDropdown?` | `(props: DropdownRenderProps) => ReactNode` | Full custom dropdown rendering |
|
|
91
|
+
| `aria-label?` | `string` | Accessible label for the textarea |
|
|
92
|
+
| `aria-describedby?` | `string` | ID of an element describing the textarea |
|
|
85
93
|
|
|
86
94
|
## Multiple Triggers
|
|
87
95
|
|
|
@@ -125,13 +133,14 @@ const engine = useMentionEngine({
|
|
|
125
133
|
onChange: setValue,
|
|
126
134
|
});
|
|
127
135
|
|
|
128
|
-
// engine.visible
|
|
129
|
-
// engine.mentions
|
|
130
|
-
// engine.activeTrigger
|
|
131
|
-
// engine.filteredOptions
|
|
136
|
+
// engine.visible - display text
|
|
137
|
+
// engine.mentions - active mentions with positions
|
|
138
|
+
// engine.activeTrigger - currently active trigger (or null)
|
|
139
|
+
// engine.filteredOptions - filtered suggestions
|
|
132
140
|
// engine.handleTextChange(text, caretPos)
|
|
133
141
|
// engine.handleKeyDown(event, textarea)
|
|
134
142
|
// engine.selectOption(item, textarea)
|
|
143
|
+
// engine.getItemForMention(triggerChar, key) - look up cached item for a mention
|
|
135
144
|
```
|
|
136
145
|
|
|
137
146
|
## Styling
|
|
@@ -148,6 +157,69 @@ Mentionize uses a transparent textarea overlaid on a highlighted div. Apply styl
|
|
|
148
157
|
/>
|
|
149
158
|
```
|
|
150
159
|
|
|
160
|
+
### Conditional Mention Styling
|
|
161
|
+
|
|
162
|
+
Use a function for `mentionClassName` to style mentions dynamically based on the underlying item data:
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import type { MentionItemData } from "mentionize";
|
|
166
|
+
|
|
167
|
+
const userTrigger: MentionTrigger<User> = {
|
|
168
|
+
trigger: "@",
|
|
169
|
+
mentionClassName: (mention: MentionItemData) => {
|
|
170
|
+
const user = mention.item as User;
|
|
171
|
+
switch (user?.role) {
|
|
172
|
+
case "Engineer": return "mention-engineer";
|
|
173
|
+
case "Designer": return "mention-designer";
|
|
174
|
+
case "PM": return "mention-pm";
|
|
175
|
+
default: return "mention-user";
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
// Apply the same conditional styling to dropdown options
|
|
179
|
+
optionClassName: (user) => {
|
|
180
|
+
switch (user.role) {
|
|
181
|
+
case "Engineer": return "mention-engineer";
|
|
182
|
+
case "Designer": return "mention-designer";
|
|
183
|
+
case "PM": return "mention-pm";
|
|
184
|
+
default: return "mention-user";
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
// ...other config
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The `MentionItemData` object contains `key`, `displayText`, `trigger`, and `item` (the original cached item). Use `optionClassName` (string or function receiving the item directly) to apply matching styles to dropdown options.
|
|
192
|
+
|
|
193
|
+
### Action Triggers
|
|
194
|
+
|
|
195
|
+
Use `onSelect` to create triggers that run an action instead of inserting a mention. The callback receives the selected item and returns a string to insert as plain text, or `null` to cancel:
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
const commandTrigger: MentionTrigger<Command> = {
|
|
199
|
+
trigger: "/",
|
|
200
|
+
displayText: (cmd) => cmd.label,
|
|
201
|
+
// serialize/pattern/parseMatch still needed for the dropdown
|
|
202
|
+
serialize: (cmd) => `/[${cmd.label}](cmd:${cmd.id})`,
|
|
203
|
+
pattern: /\/\[([^\]]+)\]\(cmd:([^)]+)\)/g,
|
|
204
|
+
parseMatch: (match) => ({ displayText: match[1]!, key: match[2]! }),
|
|
205
|
+
options: [
|
|
206
|
+
{ id: "date", label: "Insert Date" },
|
|
207
|
+
{ id: "emoji", label: "Pick Emoji" },
|
|
208
|
+
],
|
|
209
|
+
onSelect: async (cmd) => {
|
|
210
|
+
if (cmd.id === "date") return new Date().toLocaleDateString();
|
|
211
|
+
if (cmd.id === "emoji") {
|
|
212
|
+
// simulate async work
|
|
213
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
214
|
+
return "🎉";
|
|
215
|
+
}
|
|
216
|
+
return null; // cancel — nothing inserted
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
When `onSelect` is defined, selecting an option calls the function instead of inserting a mention. The trigger text and query are replaced by the returned string.
|
|
222
|
+
|
|
151
223
|
Per-trigger mention highlights can be styled via `mentionClassName`:
|
|
152
224
|
|
|
153
225
|
```tsx
|
|
@@ -5,6 +5,7 @@ interface MentionHighlighterProps {
|
|
|
5
5
|
mentions: ActiveMention[];
|
|
6
6
|
triggers: MentionTrigger<any>[];
|
|
7
7
|
textareaRef: React.RefObject<HTMLTextAreaElement | null>;
|
|
8
|
+
getItemForMention?: (triggerChar: string, key: string) => unknown;
|
|
8
9
|
className?: string;
|
|
9
10
|
style?: React.CSSProperties;
|
|
10
11
|
}
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { MentionHighlighter } from "./MentionHighlighter.tsx";
|
|
|
3
3
|
export { MentionDropdown } from "./MentionDropdown.tsx";
|
|
4
4
|
export { useMentionEngine } from "./useMentionEngine.ts";
|
|
5
5
|
export { useCaretPosition } from "./useCaretPosition.ts";
|
|
6
|
-
export type { MentionTrigger, MentionInputProps, ActiveMention, DropdownRenderProps, CaretPosition, } from "./types.ts";
|
|
6
|
+
export type { MentionTrigger, MentionItemData, MentionInputProps, ActiveMention, DropdownRenderProps, CaretPosition, } from "./types.ts";
|
package/dist/cjs/index.js
CHANGED
|
@@ -64,6 +64,7 @@ var MentionDropdown = ({
|
|
|
64
64
|
onSelect,
|
|
65
65
|
onLoadMore,
|
|
66
66
|
loading,
|
|
67
|
+
loadingText,
|
|
67
68
|
position,
|
|
68
69
|
width,
|
|
69
70
|
className
|
|
@@ -118,10 +119,12 @@ var MentionDropdown = ({
|
|
|
118
119
|
children: [
|
|
119
120
|
items.map((item, i) => {
|
|
120
121
|
const isHighlighted = i === highlightedIndex;
|
|
122
|
+
const optCls = typeof trigger.optionClassName === "function" ? trigger.optionClassName(item) : trigger.optionClassName;
|
|
121
123
|
if (trigger.renderOption) {
|
|
122
124
|
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV("div", {
|
|
123
125
|
role: "option",
|
|
124
126
|
"aria-selected": isHighlighted,
|
|
127
|
+
className: optCls,
|
|
125
128
|
"data-mentionize-option-index": i,
|
|
126
129
|
"data-mentionize-option-highlighted": isHighlighted || undefined,
|
|
127
130
|
onMouseEnter: () => onHighlight(i),
|
|
@@ -132,6 +135,7 @@ var MentionDropdown = ({
|
|
|
132
135
|
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV("div", {
|
|
133
136
|
role: "option",
|
|
134
137
|
"aria-selected": isHighlighted,
|
|
138
|
+
className: optCls,
|
|
135
139
|
"data-mentionize-option-index": i,
|
|
136
140
|
"data-mentionize-option": "",
|
|
137
141
|
"data-mentionize-option-highlighted": isHighlighted || undefined,
|
|
@@ -142,7 +146,7 @@ var MentionDropdown = ({
|
|
|
142
146
|
}),
|
|
143
147
|
loading && /* @__PURE__ */ jsx_dev_runtime.jsxDEV("div", {
|
|
144
148
|
"data-mentionize-loading": "",
|
|
145
|
-
children: "Loading..."
|
|
149
|
+
children: loadingText ?? "Loading..."
|
|
146
150
|
}, undefined, false, undefined, this),
|
|
147
151
|
onLoadMore && !loading && /* @__PURE__ */ jsx_dev_runtime.jsxDEV("div", {
|
|
148
152
|
ref: sentinelRef,
|
|
@@ -172,6 +176,7 @@ var MentionHighlighter = ({
|
|
|
172
176
|
mentions,
|
|
173
177
|
triggers,
|
|
174
178
|
textareaRef,
|
|
179
|
+
getItemForMention,
|
|
175
180
|
className,
|
|
176
181
|
style
|
|
177
182
|
}) => {
|
|
@@ -192,9 +197,9 @@ var MentionHighlighter = ({
|
|
|
192
197
|
const sorted = mentions.slice().sort((a, b) => a.start - b.start);
|
|
193
198
|
if (!sorted.length)
|
|
194
199
|
return textToNodes(visible);
|
|
195
|
-
const
|
|
200
|
+
const triggerMap = new Map;
|
|
196
201
|
for (const t of triggers) {
|
|
197
|
-
|
|
202
|
+
triggerMap.set(t.trigger, t);
|
|
198
203
|
}
|
|
199
204
|
const nodes = [];
|
|
200
205
|
let last = 0;
|
|
@@ -204,7 +209,21 @@ var MentionHighlighter = ({
|
|
|
204
209
|
nodes.push(...textToNodes(visible.slice(last, m.start)));
|
|
205
210
|
}
|
|
206
211
|
const mentionText = visible.slice(m.start, m.end);
|
|
207
|
-
const
|
|
212
|
+
const t = triggerMap.get(m.trigger);
|
|
213
|
+
let cls = "mentionize-mention";
|
|
214
|
+
if (t) {
|
|
215
|
+
if (typeof t.mentionClassName === "function") {
|
|
216
|
+
const item = getItemForMention?.(m.trigger, m.key) ?? null;
|
|
217
|
+
cls = t.mentionClassName({
|
|
218
|
+
key: m.key,
|
|
219
|
+
displayText: m.displayText,
|
|
220
|
+
trigger: m.trigger,
|
|
221
|
+
item
|
|
222
|
+
});
|
|
223
|
+
} else if (t.mentionClassName) {
|
|
224
|
+
cls = t.mentionClassName;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
208
227
|
nodes.push(import_react2.default.createElement("span", {
|
|
209
228
|
key: `mention-${i}`,
|
|
210
229
|
className: cls,
|
|
@@ -217,7 +236,7 @@ var MentionHighlighter = ({
|
|
|
217
236
|
nodes.push(...textToNodes(visible.slice(last)));
|
|
218
237
|
}
|
|
219
238
|
return nodes;
|
|
220
|
-
}, [visible, mentions, triggers]);
|
|
239
|
+
}, [visible, mentions, triggers, getItemForMention]);
|
|
221
240
|
import_react2.useLayoutEffect(() => {
|
|
222
241
|
const el = ref.current;
|
|
223
242
|
if (!el)
|
|
@@ -618,10 +637,41 @@ function useMentionEngine(options) {
|
|
|
618
637
|
setActiveTrigger(null);
|
|
619
638
|
}
|
|
620
639
|
}, [detectActiveTrigger, emitSync]);
|
|
640
|
+
const getItemForMention = import_react4.useCallback((triggerChar, key) => {
|
|
641
|
+
const cache = getCache(triggerChar);
|
|
642
|
+
return cache.get(key) ?? null;
|
|
643
|
+
}, []);
|
|
621
644
|
const selectOption = import_react4.useCallback((item, textarea) => {
|
|
622
645
|
if (!activeTrigger)
|
|
623
646
|
return;
|
|
624
647
|
const t = activeTrigger.trigger;
|
|
648
|
+
if (t.onSelect) {
|
|
649
|
+
const before2 = visible.slice(0, activeTrigger.startPos);
|
|
650
|
+
const after2 = visible.slice(textarea.selectionStart);
|
|
651
|
+
const savedStartPos = activeTrigger.startPos;
|
|
652
|
+
setActiveTrigger(null);
|
|
653
|
+
const result = t.onSelect(item);
|
|
654
|
+
const applyResult = (value) => {
|
|
655
|
+
if (value !== null) {
|
|
656
|
+
const newVis2 = before2 + value + after2;
|
|
657
|
+
const pos2 = savedStartPos + value.length;
|
|
658
|
+
caretPosRef.current = pos2;
|
|
659
|
+
setVisible(newVis2);
|
|
660
|
+
emitSync(newVis2);
|
|
661
|
+
} else {
|
|
662
|
+
const newVis2 = before2 + after2;
|
|
663
|
+
caretPosRef.current = savedStartPos;
|
|
664
|
+
setVisible(newVis2);
|
|
665
|
+
emitSync(newVis2);
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
if (result instanceof Promise) {
|
|
669
|
+
result.then(applyResult);
|
|
670
|
+
} else {
|
|
671
|
+
applyResult(result);
|
|
672
|
+
}
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
625
675
|
const cache = getCache(t.trigger);
|
|
626
676
|
const key = getItemKey(t, item);
|
|
627
677
|
cache.set(key, item);
|
|
@@ -699,7 +749,8 @@ function useMentionEngine(options) {
|
|
|
699
749
|
loadMore,
|
|
700
750
|
rawToVisible,
|
|
701
751
|
visibleToRaw,
|
|
702
|
-
caretPosRef
|
|
752
|
+
caretPosRef,
|
|
753
|
+
getItemForMention
|
|
703
754
|
};
|
|
704
755
|
}
|
|
705
756
|
function getItemKey(trigger, item) {
|
|
@@ -739,6 +790,7 @@ var MentionInput = import_react5.forwardRef(({
|
|
|
739
790
|
highlighterClassName,
|
|
740
791
|
dropdownClassName,
|
|
741
792
|
dropdownWidth = 250,
|
|
793
|
+
loadingText,
|
|
742
794
|
renderDropdown,
|
|
743
795
|
"aria-label": ariaLabel,
|
|
744
796
|
"aria-describedby": ariaDescribedBy
|
|
@@ -811,6 +863,7 @@ var MentionInput = import_react5.forwardRef(({
|
|
|
811
863
|
mentions: engine.mentions,
|
|
812
864
|
triggers,
|
|
813
865
|
textareaRef,
|
|
866
|
+
getItemForMention: engine.getItemForMention,
|
|
814
867
|
className: highlighterClassName,
|
|
815
868
|
style: SHARED_STYLE
|
|
816
869
|
}, undefined, false, undefined, this),
|
|
@@ -868,6 +921,7 @@ var MentionInput = import_react5.forwardRef(({
|
|
|
868
921
|
onSelect: handleSelect,
|
|
869
922
|
onLoadMore: engine.searchHasMore ? engine.loadMore : undefined,
|
|
870
923
|
loading: engine.searchLoading,
|
|
924
|
+
loadingText,
|
|
871
925
|
position: dropdownPos,
|
|
872
926
|
width: dropdownWidth,
|
|
873
927
|
className: dropdownClassName
|
|
@@ -877,5 +931,5 @@ var MentionInput = import_react5.forwardRef(({
|
|
|
877
931
|
});
|
|
878
932
|
MentionInput.displayName = "MentionInput";
|
|
879
933
|
|
|
880
|
-
//# debugId=
|
|
934
|
+
//# debugId=E1E2DCC63463DE3264756E2164756E21
|
|
881
935
|
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/MentionInput.tsx", "../../src/MentionDropdown.tsx", "../../src/MentionHighlighter.tsx", "../../src/useCaretPosition.ts", "../../src/useMentionEngine.ts", "../../src/utils.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { MentionDropdown } from \"./MentionDropdown.tsx\";\nimport { MentionHighlighter } from \"./MentionHighlighter.tsx\";\nimport type { CaretPosition, MentionInputProps } from \"./types.ts\";\nimport { useCaretPosition } from \"./useCaretPosition.ts\";\nimport { useMentionEngine } from \"./useMentionEngine.ts\";\n\nconst SHARED_STYLE: React.CSSProperties = {\n whiteSpace: \"pre-wrap\",\n overflowWrap: \"anywhere\",\n wordBreak: \"break-word\",\n padding: \"0.5rem 0.75rem\",\n fontFamily: \"inherit\",\n fontSize: \"inherit\",\n lineHeight: \"inherit\",\n letterSpacing: \"normal\",\n boxSizing: \"border-box\",\n};\n\nexport const MentionInput = forwardRef<HTMLTextAreaElement, MentionInputProps>(\n (\n {\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n placeholder,\n disabled,\n rows = 4,\n className,\n inputClassName,\n highlighterClassName,\n dropdownClassName,\n dropdownWidth = 250,\n renderDropdown,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n },\n ref\n ) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n useImperativeHandle(ref, () => textareaRef.current!);\n\n const engine = useMentionEngine({\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n });\n\n // Restore caret position after render, then clear so we don't\n // fight the browser on subsequent renders (like arrow-key navigation)\n useLayoutEffect(() => {\n const pos = engine.caretPosRef.current;\n const ta = textareaRef.current;\n if (pos !== null && ta && document.activeElement === ta) {\n ta.setSelectionRange(pos, pos);\n engine.caretPosRef.current = null;\n }\n });\n\n const { mirrorRef, getCaretPosition } = useCaretPosition(dropdownWidth);\n const [dropdownPos, setDropdownPos] = useState<CaretPosition | null>(null);\n\n // Update dropdown position when active trigger changes\n useEffect(() => {\n if (engine.activeTrigger && textareaRef.current) {\n requestAnimationFrame(() => {\n const pos = getCaretPosition(textareaRef.current!);\n if (pos) setDropdownPos(pos);\n });\n } else {\n setDropdownPos(null);\n }\n }, [engine.activeTrigger, engine.visible, getCaretPosition]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n engine.handleTextChange(e.target.value, e.target.selectionStart);\n },\n [engine.handleTextChange]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (textareaRef.current) {\n engine.handleKeyDown(e, textareaRef.current);\n }\n },\n [engine.handleKeyDown]\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const ta = textareaRef.current;\n if (!ta) return;\n const txt = e.clipboardData.getData(\"text\");\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n const newText =\n engine.visible.slice(0, start) + txt + engine.visible.slice(end);\n e.preventDefault();\n engine.handleTextChange(newText, start + txt.length);\n },\n [engine.visible, engine.handleTextChange]\n );\n\n const handleBlur = useCallback(() => {\n // delay allows dropdown click to fire first\n setTimeout(() => engine.closeSuggestions(), 150);\n }, [engine.closeSuggestions]);\n\n const handleSelect = useCallback(\n (item: unknown) => {\n if (textareaRef.current) {\n engine.selectOption(item, textareaRef.current);\n }\n },\n [engine.selectOption]\n );\n\n const showDropdown = engine.activeTrigger !== null && dropdownPos !== null;\n\n return (\n <div\n className={className}\n style={{ position: \"relative\" }}\n data-mentionize-container=\"\"\n >\n <MentionHighlighter\n visible={engine.visible}\n mentions={engine.mentions}\n triggers={triggers}\n textareaRef={textareaRef}\n className={highlighterClassName}\n style={SHARED_STYLE}\n />\n\n <textarea\n ref={textareaRef}\n value={engine.visible}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onBlur={handleBlur}\n rows={rows}\n placeholder={placeholder}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n aria-autocomplete=\"list\"\n aria-expanded={showDropdown}\n className={inputClassName}\n style={{\n ...SHARED_STYLE,\n position: \"relative\",\n width: \"100%\",\n resize: \"vertical\",\n background: \"transparent\",\n color: \"transparent\",\n caretColor: \"CanvasText\",\n zIndex: 10,\n }}\n data-mentionize-input=\"\"\n />\n\n {/* Caret mirror div */}\n <div\n ref={mirrorRef}\n aria-hidden\n style={{\n position: \"absolute\",\n top: 0,\n left: -9999,\n visibility: \"hidden\",\n ...SHARED_STYLE,\n }}\n data-mentionize-mirror=\"\"\n />\n\n {showDropdown && engine.activeTrigger && (\n renderDropdown ? (\n renderDropdown({\n items: engine.filteredOptions,\n highlightedIndex: engine.highlightIndex,\n onSelect: handleSelect,\n onHighlight: engine.setHighlightIndex,\n loading: engine.searchLoading,\n onLoadMore: engine.searchHasMore ? engine.loadMore : undefined,\n })\n ) : (\n <MentionDropdown\n items={engine.filteredOptions}\n trigger={engine.activeTrigger.trigger}\n highlightedIndex={engine.highlightIndex}\n onHighlight={engine.setHighlightIndex}\n onSelect={handleSelect}\n onLoadMore={engine.searchHasMore ? engine.loadMore : undefined}\n loading={engine.searchLoading}\n position={dropdownPos}\n width={dropdownWidth}\n className={dropdownClassName}\n />\n )\n )}\n </div>\n );\n }\n);\n\nMentionInput.displayName = \"MentionInput\";\n",
|
|
6
|
-
"import React, { useCallback, useEffect, useRef } from \"react\";\nimport type { CaretPosition, MentionTrigger } from \"./types.ts\";\n\ninterface MentionDropdownProps {\n items: unknown[];\n trigger: MentionTrigger<any>;\n highlightedIndex: number;\n onHighlight: (index: number) => void;\n onSelect: (item: unknown) => void;\n onLoadMore?: () => void;\n loading: boolean;\n position: CaretPosition;\n width: number;\n className?: string;\n}\n\nexport const MentionDropdown: React.FC<MentionDropdownProps> = ({\n items,\n trigger,\n highlightedIndex,\n onHighlight,\n onSelect,\n onLoadMore,\n loading,\n position,\n width,\n className,\n}) => {\n const listRef = useRef<HTMLDivElement>(null);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // IntersectionObserver for infinite scroll\n useEffect(() => {\n if (!onLoadMore || !sentinelRef.current) return;\n const sentinel = sentinelRef.current;\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0]?.isIntersecting) {\n onLoadMore();\n }\n },\n { root: listRef.current, threshold: 0.1 }\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [onLoadMore]);\n\n // Ensure highlighted item is visible\n useEffect(() => {\n const container = listRef.current;\n if (!container) return;\n const highlighted = container.querySelector(\n `[data-mentionize-option-index=\"${highlightedIndex}\"]`\n ) as HTMLElement | null;\n if (highlighted) {\n highlighted.scrollIntoView({ block: \"nearest\" });\n }\n }, [highlightedIndex]);\n\n // flip above if near bottom of viewport\n const maxHeight = 240;\n const gap = 4;\n const spaceBelow = window.innerHeight - position.top - gap;\n const flipAbove = spaceBelow < maxHeight && position.top > maxHeight;\n\n const style: React.CSSProperties = {\n position: \"fixed\",\n width,\n maxHeight,\n overflowY: \"auto\",\n zIndex: 50,\n ...(flipAbove\n ? { bottom: window.innerHeight - position.top + gap, left: position.left }\n : { top: position.top + gap, left: position.left }),\n };\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault(); // prevent blur of input\n }, []);\n\n if (!items.length && !loading) return null;\n\n return (\n <div\n ref={listRef}\n role=\"listbox\"\n className={className}\n style={style}\n data-mentionize-dropdown=\"\"\n onMouseDown={handleMouseDown}\n >\n {items.map((item, i) => {\n const isHighlighted = i === highlightedIndex;\n\n if (trigger.renderOption) {\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n data-mentionize-option-index={i}\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.renderOption(item, isHighlighted)}\n </div>\n );\n }\n\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n data-mentionize-option-index={i}\n data-mentionize-option=\"\"\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.displayText(item)}\n </div>\n );\n })}\n {loading && (\n <div data-mentionize-loading=\"\">Loading
|
|
7
|
-
"import React, { useEffect, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\n\ninterface MentionHighlighterProps {\n visible: string;\n mentions: ActiveMention[];\n triggers: MentionTrigger<any>[];\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/** Split a string so that newlines become <br/> elements */\nfunction textToNodes(text: string): React.ReactNode[] {\n const parts = text.split(\"\\n\");\n const nodes: React.ReactNode[] = [];\n for (let i = 0; i < parts.length; i++) {\n if (i > 0) nodes.push(React.createElement(\"br\", { key: `br-${i}` }));\n if (parts[i]) nodes.push(parts[i]);\n }\n return nodes;\n}\n\nexport const MentionHighlighter: React.FC<MentionHighlighterProps> = ({\n visible,\n mentions,\n triggers,\n textareaRef,\n className,\n style,\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n\n // Sync scroll with textarea\n useEffect(() => {\n const textarea = textareaRef.current;\n const highlighter = ref.current;\n if (!textarea || !highlighter) return;\n\n const onScroll = () => {\n highlighter.scrollTop = textarea.scrollTop;\n highlighter.scrollLeft = textarea.scrollLeft;\n };\n\n textarea.addEventListener(\"scroll\", onScroll);\n return () => textarea.removeEventListener(\"scroll\", onScroll);\n }, [textareaRef]);\n\n const children = useMemo(() => {\n const sorted = mentions.slice().sort((a, b) => a.start - b.start);\n if (!sorted.length) return textToNodes(visible);\n\n const
|
|
5
|
+
"import React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { MentionDropdown } from \"./MentionDropdown.tsx\";\nimport { MentionHighlighter } from \"./MentionHighlighter.tsx\";\nimport type { CaretPosition, MentionInputProps } from \"./types.ts\";\nimport { useCaretPosition } from \"./useCaretPosition.ts\";\nimport { useMentionEngine } from \"./useMentionEngine.ts\";\n\nconst SHARED_STYLE: React.CSSProperties = {\n whiteSpace: \"pre-wrap\",\n overflowWrap: \"anywhere\",\n wordBreak: \"break-word\",\n padding: \"0.5rem 0.75rem\",\n fontFamily: \"inherit\",\n fontSize: \"inherit\",\n lineHeight: \"inherit\",\n letterSpacing: \"normal\",\n boxSizing: \"border-box\",\n};\n\nexport const MentionInput = forwardRef<HTMLTextAreaElement, MentionInputProps>(\n (\n {\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n placeholder,\n disabled,\n rows = 4,\n className,\n inputClassName,\n highlighterClassName,\n dropdownClassName,\n dropdownWidth = 250,\n loadingText,\n renderDropdown,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n },\n ref\n ) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n useImperativeHandle(ref, () => textareaRef.current!);\n\n const engine = useMentionEngine({\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n });\n\n // Restore caret position after render, then clear so we don't\n // fight the browser on subsequent renders (like arrow-key navigation)\n useLayoutEffect(() => {\n const pos = engine.caretPosRef.current;\n const ta = textareaRef.current;\n if (pos !== null && ta && document.activeElement === ta) {\n ta.setSelectionRange(pos, pos);\n engine.caretPosRef.current = null;\n }\n });\n\n const { mirrorRef, getCaretPosition } = useCaretPosition(dropdownWidth);\n const [dropdownPos, setDropdownPos] = useState<CaretPosition | null>(null);\n\n // Update dropdown position when active trigger changes\n useEffect(() => {\n if (engine.activeTrigger && textareaRef.current) {\n requestAnimationFrame(() => {\n const pos = getCaretPosition(textareaRef.current!);\n if (pos) setDropdownPos(pos);\n });\n } else {\n setDropdownPos(null);\n }\n }, [engine.activeTrigger, engine.visible, getCaretPosition]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n engine.handleTextChange(e.target.value, e.target.selectionStart);\n },\n [engine.handleTextChange]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (textareaRef.current) {\n engine.handleKeyDown(e, textareaRef.current);\n }\n },\n [engine.handleKeyDown]\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const ta = textareaRef.current;\n if (!ta) return;\n const txt = e.clipboardData.getData(\"text\");\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n const newText =\n engine.visible.slice(0, start) + txt + engine.visible.slice(end);\n e.preventDefault();\n engine.handleTextChange(newText, start + txt.length);\n },\n [engine.visible, engine.handleTextChange]\n );\n\n const handleBlur = useCallback(() => {\n // delay allows dropdown click to fire first\n setTimeout(() => engine.closeSuggestions(), 150);\n }, [engine.closeSuggestions]);\n\n const handleSelect = useCallback(\n (item: unknown) => {\n if (textareaRef.current) {\n engine.selectOption(item, textareaRef.current);\n }\n },\n [engine.selectOption]\n );\n\n const showDropdown = engine.activeTrigger !== null && dropdownPos !== null;\n\n return (\n <div\n className={className}\n style={{ position: \"relative\" }}\n data-mentionize-container=\"\"\n >\n <MentionHighlighter\n visible={engine.visible}\n mentions={engine.mentions}\n triggers={triggers}\n textareaRef={textareaRef}\n getItemForMention={engine.getItemForMention}\n className={highlighterClassName}\n style={SHARED_STYLE}\n />\n\n <textarea\n ref={textareaRef}\n value={engine.visible}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onBlur={handleBlur}\n rows={rows}\n placeholder={placeholder}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n aria-autocomplete=\"list\"\n aria-expanded={showDropdown}\n className={inputClassName}\n style={{\n ...SHARED_STYLE,\n position: \"relative\",\n width: \"100%\",\n resize: \"vertical\",\n background: \"transparent\",\n color: \"transparent\",\n caretColor: \"CanvasText\",\n zIndex: 10,\n }}\n data-mentionize-input=\"\"\n />\n\n {/* Caret mirror div */}\n <div\n ref={mirrorRef}\n aria-hidden\n style={{\n position: \"absolute\",\n top: 0,\n left: -9999,\n visibility: \"hidden\",\n ...SHARED_STYLE,\n }}\n data-mentionize-mirror=\"\"\n />\n\n {showDropdown && engine.activeTrigger && (\n renderDropdown ? (\n renderDropdown({\n items: engine.filteredOptions,\n highlightedIndex: engine.highlightIndex,\n onSelect: handleSelect,\n onHighlight: engine.setHighlightIndex,\n loading: engine.searchLoading,\n onLoadMore: engine.searchHasMore ? engine.loadMore : undefined,\n })\n ) : (\n <MentionDropdown\n items={engine.filteredOptions}\n trigger={engine.activeTrigger.trigger}\n highlightedIndex={engine.highlightIndex}\n onHighlight={engine.setHighlightIndex}\n onSelect={handleSelect}\n onLoadMore={engine.searchHasMore ? engine.loadMore : undefined}\n loading={engine.searchLoading}\n loadingText={loadingText}\n position={dropdownPos}\n width={dropdownWidth}\n className={dropdownClassName}\n />\n )\n )}\n </div>\n );\n }\n);\n\nMentionInput.displayName = \"MentionInput\";\n",
|
|
6
|
+
"import React, { useCallback, useEffect, useRef } from \"react\";\nimport type { CaretPosition, MentionTrigger } from \"./types.ts\";\n\ninterface MentionDropdownProps {\n items: unknown[];\n trigger: MentionTrigger<any>;\n highlightedIndex: number;\n onHighlight: (index: number) => void;\n onSelect: (item: unknown) => void;\n onLoadMore?: () => void;\n loading: boolean;\n loadingText?: string;\n position: CaretPosition;\n width: number;\n className?: string;\n}\n\nexport const MentionDropdown: React.FC<MentionDropdownProps> = ({\n items,\n trigger,\n highlightedIndex,\n onHighlight,\n onSelect,\n onLoadMore,\n loading,\n loadingText,\n position,\n width,\n className,\n}) => {\n const listRef = useRef<HTMLDivElement>(null);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // IntersectionObserver for infinite scroll\n useEffect(() => {\n if (!onLoadMore || !sentinelRef.current) return;\n const sentinel = sentinelRef.current;\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0]?.isIntersecting) {\n onLoadMore();\n }\n },\n { root: listRef.current, threshold: 0.1 }\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [onLoadMore]);\n\n // Ensure highlighted item is visible\n useEffect(() => {\n const container = listRef.current;\n if (!container) return;\n const highlighted = container.querySelector(\n `[data-mentionize-option-index=\"${highlightedIndex}\"]`\n ) as HTMLElement | null;\n if (highlighted) {\n highlighted.scrollIntoView({ block: \"nearest\" });\n }\n }, [highlightedIndex]);\n\n // flip above if near bottom of viewport\n const maxHeight = 240;\n const gap = 4;\n const spaceBelow = window.innerHeight - position.top - gap;\n const flipAbove = spaceBelow < maxHeight && position.top > maxHeight;\n\n const style: React.CSSProperties = {\n position: \"fixed\",\n width,\n maxHeight,\n overflowY: \"auto\",\n zIndex: 50,\n ...(flipAbove\n ? { bottom: window.innerHeight - position.top + gap, left: position.left }\n : { top: position.top + gap, left: position.left }),\n };\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault(); // prevent blur of input\n }, []);\n\n if (!items.length && !loading) return null;\n\n return (\n <div\n ref={listRef}\n role=\"listbox\"\n className={className}\n style={style}\n data-mentionize-dropdown=\"\"\n onMouseDown={handleMouseDown}\n >\n {items.map((item, i) => {\n const isHighlighted = i === highlightedIndex;\n const optCls = typeof trigger.optionClassName === \"function\"\n ? trigger.optionClassName(item)\n : trigger.optionClassName;\n\n if (trigger.renderOption) {\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n className={optCls}\n data-mentionize-option-index={i}\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.renderOption(item, isHighlighted)}\n </div>\n );\n }\n\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n className={optCls}\n data-mentionize-option-index={i}\n data-mentionize-option=\"\"\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.displayText(item)}\n </div>\n );\n })}\n {loading && (\n <div data-mentionize-loading=\"\">{loadingText ?? \"Loading...\"}</div>\n )}\n {onLoadMore && !loading && (\n <div ref={sentinelRef} style={{ height: 1 }} aria-hidden />\n )}\n </div>\n );\n};\n",
|
|
7
|
+
"import React, { useEffect, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\n\ninterface MentionHighlighterProps {\n visible: string;\n mentions: ActiveMention[];\n triggers: MentionTrigger<any>[];\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n getItemForMention?: (triggerChar: string, key: string) => unknown;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/** Split a string so that newlines become <br/> elements */\nfunction textToNodes(text: string): React.ReactNode[] {\n const parts = text.split(\"\\n\");\n const nodes: React.ReactNode[] = [];\n for (let i = 0; i < parts.length; i++) {\n if (i > 0) nodes.push(React.createElement(\"br\", { key: `br-${i}` }));\n if (parts[i]) nodes.push(parts[i]);\n }\n return nodes;\n}\n\nexport const MentionHighlighter: React.FC<MentionHighlighterProps> = ({\n visible,\n mentions,\n triggers,\n textareaRef,\n getItemForMention,\n className,\n style,\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n\n // Sync scroll with textarea\n useEffect(() => {\n const textarea = textareaRef.current;\n const highlighter = ref.current;\n if (!textarea || !highlighter) return;\n\n const onScroll = () => {\n highlighter.scrollTop = textarea.scrollTop;\n highlighter.scrollLeft = textarea.scrollLeft;\n };\n\n textarea.addEventListener(\"scroll\", onScroll);\n return () => textarea.removeEventListener(\"scroll\", onScroll);\n }, [textareaRef]);\n\n const children = useMemo(() => {\n const sorted = mentions.slice().sort((a, b) => a.start - b.start);\n if (!sorted.length) return textToNodes(visible);\n\n const triggerMap = new Map<string, MentionTrigger<any>>();\n for (const t of triggers) {\n triggerMap.set(t.trigger, t);\n }\n\n const nodes: React.ReactNode[] = [];\n let last = 0;\n for (let i = 0; i < sorted.length; i++) {\n const m = sorted[i]!;\n // Text before this mention\n if (last < m.start) {\n nodes.push(...textToNodes(visible.slice(last, m.start)));\n }\n\n const mentionText = visible.slice(m.start, m.end);\n const t = triggerMap.get(m.trigger);\n let cls = \"mentionize-mention\";\n if (t) {\n if (typeof t.mentionClassName === \"function\") {\n const item = getItemForMention?.(m.trigger, m.key) ?? null;\n cls = t.mentionClassName({\n key: m.key,\n displayText: m.displayText,\n trigger: m.trigger,\n item,\n });\n } else if (t.mentionClassName) {\n cls = t.mentionClassName;\n }\n }\n nodes.push(\n React.createElement(\n \"span\",\n {\n key: `mention-${i}`,\n className: cls,\n \"data-mentionize-trigger\": m.trigger,\n \"data-mentionize-key\": m.key,\n },\n mentionText\n )\n );\n last = m.end;\n }\n // after last mention\n if (last < visible.length) {\n nodes.push(...textToNodes(visible.slice(last)));\n }\n return nodes;\n }, [visible, mentions, triggers, getItemForMention]);\n\n // After render, neutralize horizontal box-model impact of mention spans\n // so user-applied padding/border/margin don't shift overlay text relative to the textarea.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n const spans = el.querySelectorAll<HTMLElement>(\"[data-mentionize-trigger]\");\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i]!;\n // Reset any previous compensation before measuring\n span.style.marginLeft = \"\";\n span.style.marginRight = \"\";\n const cs = getComputedStyle(span);\n const extraLeft =\n parseFloat(cs.paddingLeft) +\n parseFloat(cs.borderLeftWidth) +\n parseFloat(cs.marginLeft);\n const extraRight =\n parseFloat(cs.paddingRight) +\n parseFloat(cs.borderRightWidth) +\n parseFloat(cs.marginRight);\n if (extraLeft) span.style.marginLeft = `${-extraLeft}px`;\n if (extraRight) span.style.marginRight = `${-extraRight}px`;\n }\n });\n\n return React.createElement(\n \"div\",\n {\n ref,\n className,\n style: {\n position: \"absolute\" as const,\n inset: 0,\n pointerEvents: \"none\" as const,\n overflow: \"auto\",\n ...style,\n },\n \"aria-hidden\": true,\n \"data-mentionize-highlighter\": \"\",\n },\n ...children\n );\n};\n",
|
|
8
8
|
"import { useCallback, useRef } from \"react\";\nimport type { CaretPosition } from \"./types.ts\";\n\nconst SHARED_STYLE_PROPS = [\n \"whiteSpace\",\n \"overflowWrap\",\n \"wordBreak\",\n \"padding\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"fontFamily\",\n \"fontSize\",\n \"fontWeight\",\n \"lineHeight\",\n \"letterSpacing\",\n \"tabSize\",\n \"boxSizing\",\n \"borderWidth\",\n \"borderStyle\",\n] as const;\n\nexport function useCaretPosition(dropdownWidth: number) {\n const mirrorRef = useRef<HTMLDivElement>(null);\n\n const getCaretPosition = useCallback(\n (\n textarea: HTMLTextAreaElement,\n caretIndex?: number,\n textOverride?: string\n ): CaretPosition | null => {\n const mirror = mirrorRef.current;\n if (!mirror) return null;\n\n const caret = caretIndex ?? textarea.selectionStart;\n const source = textOverride ?? textarea.value;\n const before = source.slice(0, caret);\n\n // Copy textarea computed styles to mirror\n const computed = getComputedStyle(textarea);\n for (const prop of SHARED_STYLE_PROPS) {\n (mirror.style as any)[prop] = (computed as any)[prop];\n }\n mirror.style.width = `${textarea.offsetWidth}px`;\n\n mirror.textContent = before;\n\n const span = document.createElement(\"span\");\n span.textContent = \"\\u200b\";\n mirror.appendChild(span);\n mirror.scrollTop = textarea.scrollTop;\n\n const spanRect = span.getBoundingClientRect();\n const mirrorRect = mirror.getBoundingClientRect();\n const textareaRect = textarea.getBoundingClientRect();\n\n const top =\n textareaRect.top +\n (spanRect.top - mirrorRect.top) -\n textarea.scrollTop +\n span.offsetHeight;\n let left = textareaRect.left + (spanRect.left - mirrorRect.left);\n\n // Clamp to viewport\n if (left + dropdownWidth > window.innerWidth - 8) {\n left = window.innerWidth - dropdownWidth - 8;\n }\n if (left < 8) left = 8;\n\n mirror.innerHTML = \"\";\n\n return {\n top: Math.min(Math.max(top, 8), window.innerHeight - 8),\n left,\n };\n },\n [dropdownWidth]\n );\n\n return { mirrorRef, getCaretPosition };\n}\n",
|
|
9
|
-
"import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\nimport { escapeRegex } from \"./utils.ts\";\n\ninterface ActiveTriggerState {\n trigger: MentionTrigger<any>;\n query: string;\n startPos: number; // where the trigger character is in the visible text\n}\n\ninterface SearchState {\n items: unknown[];\n page: number;\n hasMore: boolean;\n loading: boolean;\n}\n\ninterface MentionEngineOptions {\n triggers: MentionTrigger<any>[];\n value?: string;\n defaultValue?: string;\n onChange?: (raw: string) => void;\n onMentionsChange?: (mentions: ActiveMention[]) => void;\n}\n\n// Detect mentions in visible text\nfunction detectMentionsInText(\n visibleText: string,\n triggers: MentionTrigger<any>[],\n getCache: (triggerChar: string) => Map<string, unknown>,\n): ActiveMention[] {\n const all: ActiveMention[] = [];\n\n for (const t of triggers) {\n const triggerChar = t.trigger;\n if (!visibleText.includes(triggerChar)) continue;\n\n const cache = getCache(triggerChar);\n const knownItems: { displayText: string; key: string; item: unknown }[] =\n [];\n\n if (t.options) {\n for (const item of t.options) {\n knownItems.push({\n displayText: t.displayText(item),\n key: getItemKey(t, item),\n item,\n });\n }\n }\n\n for (const [key, item] of cache.entries()) {\n if (item !== null) {\n const dt = t.displayText(item);\n if (!knownItems.some((k) => k.key === key)) {\n knownItems.push({ displayText: dt, key, item });\n }\n }\n }\n\n if (!knownItems.length) continue;\n\n const compiled = knownItems.map((ki) => {\n const pat = \"^\" + escapeRegex(ki.displayText).replace(/\\s+/g, \"\\\\s+\");\n return { ...ki, re: new RegExp(pat, \"i\") };\n });\n\n const positions: number[] = [];\n let idx = visibleText.indexOf(triggerChar);\n while (idx !== -1) {\n positions.push(idx);\n idx = visibleText.indexOf(triggerChar, idx + 1);\n }\n\n const candidates: ActiveMention[] = [];\n for (const pos of positions) {\n const after = visibleText.slice(pos + triggerChar.length);\n for (const c of compiled) {\n const match = c.re.exec(after);\n if (!match) continue;\n const matched = match[0];\n const end = pos + triggerChar.length + matched.length;\n const next = visibleText[end];\n if (next && !/[\\s,.:;!?)}\\]]/.test(next)) continue;\n candidates.push({\n trigger: triggerChar,\n displayText: matched,\n key: c.key,\n start: pos,\n end,\n });\n }\n }\n\n candidates.sort((a, b) =>\n a.start !== b.start\n ? a.start - b.start\n : b.end - b.start - (a.end - a.start),\n );\n for (const c of candidates) {\n const overlaps = all.some(\n (f) => Math.max(f.start, c.start) < Math.min(f.end, c.end),\n );\n if (!overlaps) all.push(c);\n }\n }\n\n return all;\n}\n\n// Shallow-compare two mention arrays\nfunction mentionsEqual(a: ActiveMention[], b: ActiveMention[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i]!;\n const bi = b[i]!;\n if (ai.start !== bi.start || ai.end !== bi.end || ai.key !== bi.key)\n return false;\n }\n return true;\n}\n\nexport function useMentionEngine(options: MentionEngineOptions) {\n const {\n triggers,\n value: controlledValue,\n defaultValue,\n onChange,\n onMentionsChange,\n } = options;\n\n const lastRawRef = useRef(controlledValue ?? defaultValue ?? \"\");\n const suppressEmitRef = useRef(false);\n const caretPosRef = useRef<number | null>(null);\n const prevMentionsRef = useRef<ActiveMention[]>([]);\n\n // Known items cache\n const cacheRef = useRef<Map<string, Map<string, unknown>>>(new Map());\n\n function getCache(triggerChar: string): Map<string, unknown> {\n let map = cacheRef.current.get(triggerChar);\n if (!map) {\n map = new Map();\n cacheRef.current.set(triggerChar, map);\n }\n return map;\n }\n\n // Populate cache from static options\n useEffect(() => {\n for (const t of triggers) {\n if (t.options) {\n const cache = getCache(t.trigger);\n for (const item of t.options) {\n const serialized = t.serialize(item);\n // Extract key by running pattern on the serialized form\n const re = new RegExp(\n t.pattern.source,\n t.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n const { key } = t.parseMatch(m);\n cache.set(key, item);\n }\n }\n }\n }\n }, [triggers]);\n\n // Convert raw to visible text\n const rawToVisible = useCallback(\n (raw: string): string => {\n let result = raw;\n for (const t of triggers) {\n const globalRe = new RegExp(\n t.pattern.source,\n t.pattern.flags.includes(\"g\")\n ? t.pattern.flags\n : t.pattern.flags + \"g\",\n );\n const parts: string[] = [];\n let lastIndex = 0;\n let m: RegExpExecArray | null;\n globalRe.lastIndex = 0;\n while ((m = globalRe.exec(result)) !== null) {\n parts.push(result.slice(lastIndex, m.index));\n const parsed = t.parseMatch(m);\n // Cache the item data from the match\n const cache = getCache(t.trigger);\n // placeholder for unmatched items\n if (!cache.has(parsed.key)) {\n cache.set(parsed.key, null);\n }\n parts.push(t.trigger + parsed.displayText);\n lastIndex = m.index + m[0].length;\n if (!t.pattern.flags.includes(\"g\")) break;\n }\n parts.push(result.slice(lastIndex));\n result = parts.join(\"\");\n }\n return result;\n },\n [triggers],\n );\n\n // Initialize visible text from raw\n const [visible, setVisible] = useState<string>(() =>\n rawToVisible(controlledValue ?? defaultValue ?? \"\"),\n );\n\n // Detect mentions in visible text\n const mentions: ActiveMention[] = useMemo(() => {\n const newMentions = detectMentionsInText(visible, triggers, getCache);\n if (mentionsEqual(prevMentionsRef.current, newMentions)) {\n return prevMentionsRef.current;\n }\n prevMentionsRef.current = newMentions;\n return newMentions;\n }, [visible, triggers]);\n\n // Build raw value from visible + mentions\n const visibleToRaw = useCallback(\n (vis: string, mentionsList: ActiveMention[]): string => {\n if (!mentionsList.length) return vis;\n const ordered = mentionsList.slice().sort((a, b) => a.start - b.start);\n let raw = \"\";\n let last = 0;\n for (const m of ordered) {\n raw += vis.slice(last, m.start);\n // Find the trigger config and the cached item\n const t = triggers.find((tr) => tr.trigger === m.trigger);\n if (t) {\n const cache = getCache(t.trigger);\n const item = cache.get(m.key);\n if (item !== null && item !== undefined) {\n raw += t.serialize(item);\n } else {\n raw += vis.slice(m.start, m.end);\n }\n } else {\n raw += vis.slice(m.start, m.end);\n }\n last = m.end;\n }\n raw += vis.slice(last);\n return raw;\n },\n [triggers],\n );\n\n // Synchronously emit raw value + mentions after visible text changes\n const emitSync = useCallback(\n (newVisible: string) => {\n const newMentions = detectMentionsInText(newVisible, triggers, getCache);\n\n if (!mentionsEqual(prevMentionsRef.current, newMentions)) {\n prevMentionsRef.current = newMentions;\n }\n\n const raw = visibleToRaw(newVisible, prevMentionsRef.current);\n if (raw !== lastRawRef.current) {\n lastRawRef.current = raw;\n onChange?.(raw);\n }\n onMentionsChange?.(prevMentionsRef.current);\n },\n [triggers, visibleToRaw, onChange, onMentionsChange],\n );\n\n useEffect(() => {\n if (controlledValue === undefined) return;\n if (controlledValue === lastRawRef.current) return;\n lastRawRef.current = controlledValue;\n suppressEmitRef.current = true;\n setVisible(rawToVisible(controlledValue));\n }, [controlledValue, rawToVisible]);\n\n const [activeTrigger, setActiveTrigger] = useState<ActiveTriggerState | null>(\n null,\n );\n const [searchState, setSearchState] = useState<SearchState>({\n items: [],\n page: 0,\n hasMore: false,\n loading: false,\n });\n const [highlightIndex, setHighlightIndex] = useState(0);\n const searchAbortRef = useRef<AbortController | null>(null);\n\n const detectActiveTrigger = useCallback(\n (text: string, caretPos: number): ActiveTriggerState | null => {\n // Look backwards from caret for any trigger character\n const prefix = text.slice(0, caretPos);\n for (const t of triggers) {\n const triggerChar = t.trigger;\n // Find the last occurrence of trigger char before caret\n const re = new RegExp(\n escapeRegex(triggerChar) +\n \"([^\\\\n\" +\n escapeRegex(triggerChar) +\n \"]*)$\",\n );\n const match = re.exec(prefix);\n if (match && match[1] !== undefined) {\n const query = match[1];\n // Don't activate if query contains whitespace (user moved on)\n if (/\\s/.test(query)) continue;\n return {\n trigger: t,\n query,\n startPos: match.index,\n };\n }\n }\n return null;\n },\n [triggers],\n );\n\n // Get filtered options for current trigger\n const filteredOptions = useMemo(() => {\n if (!activeTrigger) return [];\n const t = activeTrigger.trigger;\n const q = activeTrigger.query.toLowerCase();\n\n if (t.onSearch) {\n // Async mode returns search state items\n return searchState.items;\n }\n\n if (t.options) {\n if (!q) return t.options;\n return t.options.filter((item) =>\n t.displayText(item).toLowerCase().includes(q),\n );\n }\n\n return [];\n }, [activeTrigger, searchState.items]);\n\n useEffect(() => {\n if (!activeTrigger?.trigger.onSearch) return;\n\n const t = activeTrigger.trigger;\n const query = activeTrigger.query;\n\n // Abort previous search\n searchAbortRef.current?.abort();\n const controller = new AbortController();\n searchAbortRef.current = controller;\n\n setSearchState((s) => ({ ...s, loading: true, page: 0 }));\n\n const timer = setTimeout(async () => {\n try {\n const result = await t.onSearch!(query, 0);\n if (controller.signal.aborted) return;\n setSearchState({\n items: result.items,\n page: 0,\n hasMore: result.hasMore,\n loading: false,\n });\n } catch {\n if (controller.signal.aborted) return;\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, 150);\n\n return () => {\n clearTimeout(timer);\n controller.abort();\n };\n }, [activeTrigger?.trigger, activeTrigger?.query]);\n\n const loadMore = useCallback(async () => {\n if (\n !activeTrigger?.trigger.onSearch ||\n searchState.loading ||\n !searchState.hasMore\n )\n return;\n\n const t = activeTrigger.trigger;\n const nextPage = searchState.page + 1;\n setSearchState((s) => ({ ...s, loading: true }));\n\n try {\n const result = await t.onSearch!(activeTrigger.query, nextPage);\n setSearchState((s) => ({\n items: [...s.items, ...result.items],\n page: nextPage,\n hasMore: result.hasMore,\n loading: false,\n }));\n } catch {\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, [activeTrigger, searchState]);\n\n // Handle text change from textarea\n const handleTextChange = useCallback(\n (newText: string, caretPos: number) => {\n caretPosRef.current = caretPos;\n setVisible(newText);\n emitSync(newText);\n const detected = detectActiveTrigger(newText, caretPos);\n if (detected) {\n setActiveTrigger(detected);\n setHighlightIndex(0);\n } else {\n setActiveTrigger(null);\n }\n },\n [detectActiveTrigger, emitSync],\n );\n\n // Select an option from the dropdown\n const selectOption = useCallback(\n (item: unknown, textarea: HTMLTextAreaElement) => {\n if (!activeTrigger) return;\n const t = activeTrigger.trigger;\n\n // Add to cache\n const cache = getCache(t.trigger);\n const key = getItemKey(t, item);\n cache.set(key, item);\n\n const displayText = t.displayText(item);\n const mentionText = t.trigger + displayText;\n\n const before = visible.slice(0, activeTrigger.startPos);\n const after = visible.slice(textarea.selectionStart);\n const newVis = before + mentionText + \" \" + after;\n\n const pos = before.length + mentionText.length + 1;\n caretPosRef.current = pos;\n setVisible(newVis);\n emitSync(newVis);\n setActiveTrigger(null);\n },\n [activeTrigger, visible, emitSync],\n );\n\n const closeSuggestions = useCallback(() => {\n setActiveTrigger(null);\n setSearchState({ items: [], page: 0, hasMore: false, loading: false });\n }, []);\n\n // Keyboard handling\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, textarea: HTMLTextAreaElement): boolean => {\n if (!activeTrigger) return false;\n\n const len = filteredOptions.length;\n if (!len && !searchState.loading) return false;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n const next = (highlightIndex + 1) % Math.max(len, 1);\n setHighlightIndex(next);\n // Trigger load more near end\n if (\n len - 1 - next <= 3 &&\n searchState.hasMore &&\n !searchState.loading\n ) {\n loadMore();\n }\n return true;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setHighlightIndex(\n (highlightIndex - 1 + Math.max(len, 1)) % Math.max(len, 1),\n );\n return true;\n }\n if (e.key === \"Enter\") {\n e.preventDefault();\n const item = filteredOptions[highlightIndex];\n if (item) selectOption(item, textarea);\n return true;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n closeSuggestions();\n return true;\n }\n return false;\n },\n [\n activeTrigger,\n filteredOptions,\n highlightIndex,\n searchState,\n selectOption,\n closeSuggestions,\n loadMore,\n ],\n );\n\n return {\n visible,\n setVisible,\n mentions,\n activeTrigger,\n filteredOptions,\n highlightIndex,\n setHighlightIndex,\n searchLoading: searchState.loading,\n searchHasMore: searchState.hasMore,\n handleTextChange,\n handleKeyDown,\n selectOption,\n closeSuggestions,\n loadMore,\n rawToVisible,\n visibleToRaw,\n caretPosRef,\n };\n}\n\nfunction getItemKey(trigger: MentionTrigger<any>, item: unknown): string {\n const serialized = trigger.serialize(item);\n const re = new RegExp(\n trigger.pattern.source,\n trigger.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n return trigger.parseMatch(m).key;\n }\n return serialized;\n}\n",
|
|
9
|
+
"import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\nimport { escapeRegex } from \"./utils.ts\";\n\ninterface ActiveTriggerState {\n trigger: MentionTrigger<any>;\n query: string;\n startPos: number; // where the trigger character is in the visible text\n}\n\ninterface SearchState {\n items: unknown[];\n page: number;\n hasMore: boolean;\n loading: boolean;\n}\n\ninterface MentionEngineOptions {\n triggers: MentionTrigger<any>[];\n value?: string;\n defaultValue?: string;\n onChange?: (raw: string) => void;\n onMentionsChange?: (mentions: ActiveMention[]) => void;\n}\n\n// Detect mentions in visible text\nfunction detectMentionsInText(\n visibleText: string,\n triggers: MentionTrigger<any>[],\n getCache: (triggerChar: string) => Map<string, unknown>,\n): ActiveMention[] {\n const all: ActiveMention[] = [];\n\n for (const t of triggers) {\n const triggerChar = t.trigger;\n if (!visibleText.includes(triggerChar)) continue;\n\n const cache = getCache(triggerChar);\n const knownItems: { displayText: string; key: string; item: unknown }[] =\n [];\n\n if (t.options) {\n for (const item of t.options) {\n knownItems.push({\n displayText: t.displayText(item),\n key: getItemKey(t, item),\n item,\n });\n }\n }\n\n for (const [key, item] of cache.entries()) {\n if (item !== null) {\n const dt = t.displayText(item);\n if (!knownItems.some((k) => k.key === key)) {\n knownItems.push({ displayText: dt, key, item });\n }\n }\n }\n\n if (!knownItems.length) continue;\n\n const compiled = knownItems.map((ki) => {\n const pat = \"^\" + escapeRegex(ki.displayText).replace(/\\s+/g, \"\\\\s+\");\n return { ...ki, re: new RegExp(pat, \"i\") };\n });\n\n const positions: number[] = [];\n let idx = visibleText.indexOf(triggerChar);\n while (idx !== -1) {\n positions.push(idx);\n idx = visibleText.indexOf(triggerChar, idx + 1);\n }\n\n const candidates: ActiveMention[] = [];\n for (const pos of positions) {\n const after = visibleText.slice(pos + triggerChar.length);\n for (const c of compiled) {\n const match = c.re.exec(after);\n if (!match) continue;\n const matched = match[0];\n const end = pos + triggerChar.length + matched.length;\n const next = visibleText[end];\n if (next && !/[\\s,.:;!?)}\\]]/.test(next)) continue;\n candidates.push({\n trigger: triggerChar,\n displayText: matched,\n key: c.key,\n start: pos,\n end,\n });\n }\n }\n\n candidates.sort((a, b) =>\n a.start !== b.start\n ? a.start - b.start\n : b.end - b.start - (a.end - a.start),\n );\n for (const c of candidates) {\n const overlaps = all.some(\n (f) => Math.max(f.start, c.start) < Math.min(f.end, c.end),\n );\n if (!overlaps) all.push(c);\n }\n }\n\n return all;\n}\n\n// Shallow-compare two mention arrays\nfunction mentionsEqual(a: ActiveMention[], b: ActiveMention[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i]!;\n const bi = b[i]!;\n if (ai.start !== bi.start || ai.end !== bi.end || ai.key !== bi.key)\n return false;\n }\n return true;\n}\n\nexport function useMentionEngine(options: MentionEngineOptions) {\n const {\n triggers,\n value: controlledValue,\n defaultValue,\n onChange,\n onMentionsChange,\n } = options;\n\n const lastRawRef = useRef(controlledValue ?? defaultValue ?? \"\");\n const suppressEmitRef = useRef(false);\n const caretPosRef = useRef<number | null>(null);\n const prevMentionsRef = useRef<ActiveMention[]>([]);\n\n // Known items cache\n const cacheRef = useRef<Map<string, Map<string, unknown>>>(new Map());\n\n function getCache(triggerChar: string): Map<string, unknown> {\n let map = cacheRef.current.get(triggerChar);\n if (!map) {\n map = new Map();\n cacheRef.current.set(triggerChar, map);\n }\n return map;\n }\n\n // Populate cache from static options\n useEffect(() => {\n for (const t of triggers) {\n if (t.options) {\n const cache = getCache(t.trigger);\n for (const item of t.options) {\n const serialized = t.serialize(item);\n // Extract key by running pattern on the serialized form\n const re = new RegExp(\n t.pattern.source,\n t.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n const { key } = t.parseMatch(m);\n cache.set(key, item);\n }\n }\n }\n }\n }, [triggers]);\n\n // Convert raw to visible text\n const rawToVisible = useCallback(\n (raw: string): string => {\n let result = raw;\n for (const t of triggers) {\n const globalRe = new RegExp(\n t.pattern.source,\n t.pattern.flags.includes(\"g\")\n ? t.pattern.flags\n : t.pattern.flags + \"g\",\n );\n const parts: string[] = [];\n let lastIndex = 0;\n let m: RegExpExecArray | null;\n globalRe.lastIndex = 0;\n while ((m = globalRe.exec(result)) !== null) {\n parts.push(result.slice(lastIndex, m.index));\n const parsed = t.parseMatch(m);\n // Cache the item data from the match\n const cache = getCache(t.trigger);\n // placeholder for unmatched items\n if (!cache.has(parsed.key)) {\n cache.set(parsed.key, null);\n }\n parts.push(t.trigger + parsed.displayText);\n lastIndex = m.index + m[0].length;\n if (!t.pattern.flags.includes(\"g\")) break;\n }\n parts.push(result.slice(lastIndex));\n result = parts.join(\"\");\n }\n return result;\n },\n [triggers],\n );\n\n // Initialize visible text from raw\n const [visible, setVisible] = useState<string>(() =>\n rawToVisible(controlledValue ?? defaultValue ?? \"\"),\n );\n\n // Detect mentions in visible text\n const mentions: ActiveMention[] = useMemo(() => {\n const newMentions = detectMentionsInText(visible, triggers, getCache);\n if (mentionsEqual(prevMentionsRef.current, newMentions)) {\n return prevMentionsRef.current;\n }\n prevMentionsRef.current = newMentions;\n return newMentions;\n }, [visible, triggers]);\n\n // Build raw value from visible + mentions\n const visibleToRaw = useCallback(\n (vis: string, mentionsList: ActiveMention[]): string => {\n if (!mentionsList.length) return vis;\n const ordered = mentionsList.slice().sort((a, b) => a.start - b.start);\n let raw = \"\";\n let last = 0;\n for (const m of ordered) {\n raw += vis.slice(last, m.start);\n // Find the trigger config and the cached item\n const t = triggers.find((tr) => tr.trigger === m.trigger);\n if (t) {\n const cache = getCache(t.trigger);\n const item = cache.get(m.key);\n if (item !== null && item !== undefined) {\n raw += t.serialize(item);\n } else {\n raw += vis.slice(m.start, m.end);\n }\n } else {\n raw += vis.slice(m.start, m.end);\n }\n last = m.end;\n }\n raw += vis.slice(last);\n return raw;\n },\n [triggers],\n );\n\n // Synchronously emit raw value + mentions after visible text changes\n const emitSync = useCallback(\n (newVisible: string) => {\n const newMentions = detectMentionsInText(newVisible, triggers, getCache);\n\n if (!mentionsEqual(prevMentionsRef.current, newMentions)) {\n prevMentionsRef.current = newMentions;\n }\n\n const raw = visibleToRaw(newVisible, prevMentionsRef.current);\n if (raw !== lastRawRef.current) {\n lastRawRef.current = raw;\n onChange?.(raw);\n }\n onMentionsChange?.(prevMentionsRef.current);\n },\n [triggers, visibleToRaw, onChange, onMentionsChange],\n );\n\n useEffect(() => {\n if (controlledValue === undefined) return;\n if (controlledValue === lastRawRef.current) return;\n lastRawRef.current = controlledValue;\n suppressEmitRef.current = true;\n setVisible(rawToVisible(controlledValue));\n }, [controlledValue, rawToVisible]);\n\n const [activeTrigger, setActiveTrigger] = useState<ActiveTriggerState | null>(\n null,\n );\n const [searchState, setSearchState] = useState<SearchState>({\n items: [],\n page: 0,\n hasMore: false,\n loading: false,\n });\n const [highlightIndex, setHighlightIndex] = useState(0);\n const searchAbortRef = useRef<AbortController | null>(null);\n\n const detectActiveTrigger = useCallback(\n (text: string, caretPos: number): ActiveTriggerState | null => {\n // Look backwards from caret for any trigger character\n const prefix = text.slice(0, caretPos);\n for (const t of triggers) {\n const triggerChar = t.trigger;\n // Find the last occurrence of trigger char before caret\n const re = new RegExp(\n escapeRegex(triggerChar) +\n \"([^\\\\n\" +\n escapeRegex(triggerChar) +\n \"]*)$\",\n );\n const match = re.exec(prefix);\n if (match && match[1] !== undefined) {\n const query = match[1];\n // Don't activate if query contains whitespace (user moved on)\n if (/\\s/.test(query)) continue;\n return {\n trigger: t,\n query,\n startPos: match.index,\n };\n }\n }\n return null;\n },\n [triggers],\n );\n\n // Get filtered options for current trigger\n const filteredOptions = useMemo(() => {\n if (!activeTrigger) return [];\n const t = activeTrigger.trigger;\n const q = activeTrigger.query.toLowerCase();\n\n if (t.onSearch) {\n // Async mode returns search state items\n return searchState.items;\n }\n\n if (t.options) {\n if (!q) return t.options;\n return t.options.filter((item) =>\n t.displayText(item).toLowerCase().includes(q),\n );\n }\n\n return [];\n }, [activeTrigger, searchState.items]);\n\n useEffect(() => {\n if (!activeTrigger?.trigger.onSearch) return;\n\n const t = activeTrigger.trigger;\n const query = activeTrigger.query;\n\n // Abort previous search\n searchAbortRef.current?.abort();\n const controller = new AbortController();\n searchAbortRef.current = controller;\n\n setSearchState((s) => ({ ...s, loading: true, page: 0 }));\n\n const timer = setTimeout(async () => {\n try {\n const result = await t.onSearch!(query, 0);\n if (controller.signal.aborted) return;\n setSearchState({\n items: result.items,\n page: 0,\n hasMore: result.hasMore,\n loading: false,\n });\n } catch {\n if (controller.signal.aborted) return;\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, 150);\n\n return () => {\n clearTimeout(timer);\n controller.abort();\n };\n }, [activeTrigger?.trigger, activeTrigger?.query]);\n\n const loadMore = useCallback(async () => {\n if (\n !activeTrigger?.trigger.onSearch ||\n searchState.loading ||\n !searchState.hasMore\n )\n return;\n\n const t = activeTrigger.trigger;\n const nextPage = searchState.page + 1;\n setSearchState((s) => ({ ...s, loading: true }));\n\n try {\n const result = await t.onSearch!(activeTrigger.query, nextPage);\n setSearchState((s) => ({\n items: [...s.items, ...result.items],\n page: nextPage,\n hasMore: result.hasMore,\n loading: false,\n }));\n } catch {\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, [activeTrigger, searchState]);\n\n // Handle text change from textarea\n const handleTextChange = useCallback(\n (newText: string, caretPos: number) => {\n caretPosRef.current = caretPos;\n setVisible(newText);\n emitSync(newText);\n const detected = detectActiveTrigger(newText, caretPos);\n if (detected) {\n setActiveTrigger(detected);\n setHighlightIndex(0);\n } else {\n setActiveTrigger(null);\n }\n },\n [detectActiveTrigger, emitSync],\n );\n\n // Look up a cached item for a mention\n const getItemForMention = useCallback(\n (triggerChar: string, key: string): unknown => {\n const cache = getCache(triggerChar);\n return cache.get(key) ?? null;\n },\n [],\n );\n\n // Select an option from the dropdown\n const selectOption = useCallback(\n (item: unknown, textarea: HTMLTextAreaElement) => {\n if (!activeTrigger) return;\n const t = activeTrigger.trigger;\n\n if (t.onSelect) {\n // Action trigger mode: close dropdown, remove trigger+query, call onSelect\n const before = visible.slice(0, activeTrigger.startPos);\n const after = visible.slice(textarea.selectionStart);\n const savedStartPos = activeTrigger.startPos;\n\n setActiveTrigger(null);\n\n const result = t.onSelect(item);\n const applyResult = (value: string | null) => {\n if (value !== null) {\n const newVis = before + value + after;\n const pos = savedStartPos + value.length;\n caretPosRef.current = pos;\n setVisible(newVis);\n emitSync(newVis);\n } else {\n // null = cancel, just remove the trigger+query\n const newVis = before + after;\n caretPosRef.current = savedStartPos;\n setVisible(newVis);\n emitSync(newVis);\n }\n };\n\n if (result instanceof Promise) {\n result.then(applyResult);\n } else {\n applyResult(result);\n }\n return;\n }\n\n // Standard mention mode\n const cache = getCache(t.trigger);\n const key = getItemKey(t, item);\n cache.set(key, item);\n\n const displayText = t.displayText(item);\n const mentionText = t.trigger + displayText;\n\n const before = visible.slice(0, activeTrigger.startPos);\n const after = visible.slice(textarea.selectionStart);\n const newVis = before + mentionText + \" \" + after;\n\n const pos = before.length + mentionText.length + 1;\n caretPosRef.current = pos;\n setVisible(newVis);\n emitSync(newVis);\n setActiveTrigger(null);\n },\n [activeTrigger, visible, emitSync],\n );\n\n const closeSuggestions = useCallback(() => {\n setActiveTrigger(null);\n setSearchState({ items: [], page: 0, hasMore: false, loading: false });\n }, []);\n\n // Keyboard handling\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, textarea: HTMLTextAreaElement): boolean => {\n if (!activeTrigger) return false;\n\n const len = filteredOptions.length;\n if (!len && !searchState.loading) return false;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n const next = (highlightIndex + 1) % Math.max(len, 1);\n setHighlightIndex(next);\n // Trigger load more near end\n if (\n len - 1 - next <= 3 &&\n searchState.hasMore &&\n !searchState.loading\n ) {\n loadMore();\n }\n return true;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setHighlightIndex(\n (highlightIndex - 1 + Math.max(len, 1)) % Math.max(len, 1),\n );\n return true;\n }\n if (e.key === \"Enter\") {\n e.preventDefault();\n const item = filteredOptions[highlightIndex];\n if (item) selectOption(item, textarea);\n return true;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n closeSuggestions();\n return true;\n }\n return false;\n },\n [\n activeTrigger,\n filteredOptions,\n highlightIndex,\n searchState,\n selectOption,\n closeSuggestions,\n loadMore,\n ],\n );\n\n return {\n visible,\n setVisible,\n mentions,\n activeTrigger,\n filteredOptions,\n highlightIndex,\n setHighlightIndex,\n searchLoading: searchState.loading,\n searchHasMore: searchState.hasMore,\n handleTextChange,\n handleKeyDown,\n selectOption,\n closeSuggestions,\n loadMore,\n rawToVisible,\n visibleToRaw,\n caretPosRef,\n getItemForMention,\n };\n}\n\nfunction getItemKey(trigger: MentionTrigger<any>, item: unknown): string {\n const serialized = trigger.serialize(item);\n const re = new RegExp(\n trigger.pattern.source,\n trigger.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n return trigger.parseMatch(m).key;\n }\n return serialized;\n}\n",
|
|
10
10
|
"export function escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"
|
|
11
11
|
],
|
|
12
|
-
"mappings": "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",
|
|
13
|
-
"debugId": "
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "E1E2DCC63463DE3264756E2164756E21",
|
|
14
14
|
"names": []
|
|
15
15
|
}
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type React from "react";
|
|
2
|
+
export interface MentionItemData {
|
|
3
|
+
key: string;
|
|
4
|
+
displayText: string;
|
|
5
|
+
trigger: string;
|
|
6
|
+
item: unknown;
|
|
7
|
+
}
|
|
2
8
|
export interface MentionTrigger<T = unknown> {
|
|
3
9
|
/** The character(s) that activate this trigger (e.g., "@", "#") */
|
|
4
10
|
trigger: string;
|
|
@@ -22,10 +28,14 @@ export interface MentionTrigger<T = unknown> {
|
|
|
22
28
|
}>;
|
|
23
29
|
/** Custom option rendering */
|
|
24
30
|
renderOption?: (item: T, highlighted: boolean) => React.ReactNode;
|
|
31
|
+
/** CSS class for dropdown options, or a function for conditional styling per item */
|
|
32
|
+
optionClassName?: string | ((item: T) => string);
|
|
25
33
|
/** Custom mention highlight rendering */
|
|
26
|
-
renderMention?: (displayText: string) => React.ReactNode;
|
|
27
|
-
/** CSS class for highlighted mentions in the overlay */
|
|
28
|
-
mentionClassName?: string;
|
|
34
|
+
renderMention?: (displayText: string, item?: unknown) => React.ReactNode;
|
|
35
|
+
/** CSS class for highlighted mentions in the overlay, or a function for conditional styling */
|
|
36
|
+
mentionClassName?: string | ((mention: MentionItemData) => string);
|
|
37
|
+
/** Action trigger: called instead of inserting a mention. Return string to insert as plain text, or null to cancel. */
|
|
38
|
+
onSelect?: (item: T) => Promise<string | null> | string | null;
|
|
29
39
|
}
|
|
30
40
|
export interface MentionInputProps {
|
|
31
41
|
triggers: MentionTrigger<any>[];
|
|
@@ -48,6 +58,8 @@ export interface MentionInputProps {
|
|
|
48
58
|
dropdownClassName?: string;
|
|
49
59
|
/** Dropdown width in pixels */
|
|
50
60
|
dropdownWidth?: number;
|
|
61
|
+
/** Text shown while loading async results (default: "Loading...") */
|
|
62
|
+
loadingText?: string;
|
|
51
63
|
/** Full custom dropdown rendering */
|
|
52
64
|
renderDropdown?: (props: DropdownRenderProps) => React.ReactNode;
|
|
53
65
|
"aria-label"?: string;
|
|
@@ -29,5 +29,6 @@ export declare function useMentionEngine(options: MentionEngineOptions): {
|
|
|
29
29
|
rawToVisible: (raw: string) => string;
|
|
30
30
|
visibleToRaw: (vis: string, mentionsList: ActiveMention[]) => string;
|
|
31
31
|
caretPosRef: import("react").RefObject<number | null>;
|
|
32
|
+
getItemForMention: (triggerChar: string, key: string) => unknown;
|
|
32
33
|
};
|
|
33
34
|
export {};
|
|
@@ -5,6 +5,7 @@ interface MentionHighlighterProps {
|
|
|
5
5
|
mentions: ActiveMention[];
|
|
6
6
|
triggers: MentionTrigger<any>[];
|
|
7
7
|
textareaRef: React.RefObject<HTMLTextAreaElement | null>;
|
|
8
|
+
getItemForMention?: (triggerChar: string, key: string) => unknown;
|
|
8
9
|
className?: string;
|
|
9
10
|
style?: React.CSSProperties;
|
|
10
11
|
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { MentionHighlighter } from "./MentionHighlighter.tsx";
|
|
|
3
3
|
export { MentionDropdown } from "./MentionDropdown.tsx";
|
|
4
4
|
export { useMentionEngine } from "./useMentionEngine.ts";
|
|
5
5
|
export { useCaretPosition } from "./useCaretPosition.ts";
|
|
6
|
-
export type { MentionTrigger, MentionInputProps, ActiveMention, DropdownRenderProps, CaretPosition, } from "./types.ts";
|
|
6
|
+
export type { MentionTrigger, MentionItemData, MentionInputProps, ActiveMention, DropdownRenderProps, CaretPosition, } from "./types.ts";
|
package/dist/esm/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var MentionDropdown = ({
|
|
|
20
20
|
onSelect,
|
|
21
21
|
onLoadMore,
|
|
22
22
|
loading,
|
|
23
|
+
loadingText,
|
|
23
24
|
position,
|
|
24
25
|
width,
|
|
25
26
|
className
|
|
@@ -74,10 +75,12 @@ var MentionDropdown = ({
|
|
|
74
75
|
children: [
|
|
75
76
|
items.map((item, i) => {
|
|
76
77
|
const isHighlighted = i === highlightedIndex;
|
|
78
|
+
const optCls = typeof trigger.optionClassName === "function" ? trigger.optionClassName(item) : trigger.optionClassName;
|
|
77
79
|
if (trigger.renderOption) {
|
|
78
80
|
return /* @__PURE__ */ jsxDEV("div", {
|
|
79
81
|
role: "option",
|
|
80
82
|
"aria-selected": isHighlighted,
|
|
83
|
+
className: optCls,
|
|
81
84
|
"data-mentionize-option-index": i,
|
|
82
85
|
"data-mentionize-option-highlighted": isHighlighted || undefined,
|
|
83
86
|
onMouseEnter: () => onHighlight(i),
|
|
@@ -88,6 +91,7 @@ var MentionDropdown = ({
|
|
|
88
91
|
return /* @__PURE__ */ jsxDEV("div", {
|
|
89
92
|
role: "option",
|
|
90
93
|
"aria-selected": isHighlighted,
|
|
94
|
+
className: optCls,
|
|
91
95
|
"data-mentionize-option-index": i,
|
|
92
96
|
"data-mentionize-option": "",
|
|
93
97
|
"data-mentionize-option-highlighted": isHighlighted || undefined,
|
|
@@ -98,7 +102,7 @@ var MentionDropdown = ({
|
|
|
98
102
|
}),
|
|
99
103
|
loading && /* @__PURE__ */ jsxDEV("div", {
|
|
100
104
|
"data-mentionize-loading": "",
|
|
101
|
-
children: "Loading..."
|
|
105
|
+
children: loadingText ?? "Loading..."
|
|
102
106
|
}, undefined, false, undefined, this),
|
|
103
107
|
onLoadMore && !loading && /* @__PURE__ */ jsxDEV("div", {
|
|
104
108
|
ref: sentinelRef,
|
|
@@ -128,6 +132,7 @@ var MentionHighlighter = ({
|
|
|
128
132
|
mentions,
|
|
129
133
|
triggers,
|
|
130
134
|
textareaRef,
|
|
135
|
+
getItemForMention,
|
|
131
136
|
className,
|
|
132
137
|
style
|
|
133
138
|
}) => {
|
|
@@ -148,9 +153,9 @@ var MentionHighlighter = ({
|
|
|
148
153
|
const sorted = mentions.slice().sort((a, b) => a.start - b.start);
|
|
149
154
|
if (!sorted.length)
|
|
150
155
|
return textToNodes(visible);
|
|
151
|
-
const
|
|
156
|
+
const triggerMap = new Map;
|
|
152
157
|
for (const t of triggers) {
|
|
153
|
-
|
|
158
|
+
triggerMap.set(t.trigger, t);
|
|
154
159
|
}
|
|
155
160
|
const nodes = [];
|
|
156
161
|
let last = 0;
|
|
@@ -160,7 +165,21 @@ var MentionHighlighter = ({
|
|
|
160
165
|
nodes.push(...textToNodes(visible.slice(last, m.start)));
|
|
161
166
|
}
|
|
162
167
|
const mentionText = visible.slice(m.start, m.end);
|
|
163
|
-
const
|
|
168
|
+
const t = triggerMap.get(m.trigger);
|
|
169
|
+
let cls = "mentionize-mention";
|
|
170
|
+
if (t) {
|
|
171
|
+
if (typeof t.mentionClassName === "function") {
|
|
172
|
+
const item = getItemForMention?.(m.trigger, m.key) ?? null;
|
|
173
|
+
cls = t.mentionClassName({
|
|
174
|
+
key: m.key,
|
|
175
|
+
displayText: m.displayText,
|
|
176
|
+
trigger: m.trigger,
|
|
177
|
+
item
|
|
178
|
+
});
|
|
179
|
+
} else if (t.mentionClassName) {
|
|
180
|
+
cls = t.mentionClassName;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
164
183
|
nodes.push(React2.createElement("span", {
|
|
165
184
|
key: `mention-${i}`,
|
|
166
185
|
className: cls,
|
|
@@ -173,7 +192,7 @@ var MentionHighlighter = ({
|
|
|
173
192
|
nodes.push(...textToNodes(visible.slice(last)));
|
|
174
193
|
}
|
|
175
194
|
return nodes;
|
|
176
|
-
}, [visible, mentions, triggers]);
|
|
195
|
+
}, [visible, mentions, triggers, getItemForMention]);
|
|
177
196
|
useLayoutEffect(() => {
|
|
178
197
|
const el = ref.current;
|
|
179
198
|
if (!el)
|
|
@@ -574,10 +593,41 @@ function useMentionEngine(options) {
|
|
|
574
593
|
setActiveTrigger(null);
|
|
575
594
|
}
|
|
576
595
|
}, [detectActiveTrigger, emitSync]);
|
|
596
|
+
const getItemForMention = useCallback3((triggerChar, key) => {
|
|
597
|
+
const cache = getCache(triggerChar);
|
|
598
|
+
return cache.get(key) ?? null;
|
|
599
|
+
}, []);
|
|
577
600
|
const selectOption = useCallback3((item, textarea) => {
|
|
578
601
|
if (!activeTrigger)
|
|
579
602
|
return;
|
|
580
603
|
const t = activeTrigger.trigger;
|
|
604
|
+
if (t.onSelect) {
|
|
605
|
+
const before2 = visible.slice(0, activeTrigger.startPos);
|
|
606
|
+
const after2 = visible.slice(textarea.selectionStart);
|
|
607
|
+
const savedStartPos = activeTrigger.startPos;
|
|
608
|
+
setActiveTrigger(null);
|
|
609
|
+
const result = t.onSelect(item);
|
|
610
|
+
const applyResult = (value) => {
|
|
611
|
+
if (value !== null) {
|
|
612
|
+
const newVis2 = before2 + value + after2;
|
|
613
|
+
const pos2 = savedStartPos + value.length;
|
|
614
|
+
caretPosRef.current = pos2;
|
|
615
|
+
setVisible(newVis2);
|
|
616
|
+
emitSync(newVis2);
|
|
617
|
+
} else {
|
|
618
|
+
const newVis2 = before2 + after2;
|
|
619
|
+
caretPosRef.current = savedStartPos;
|
|
620
|
+
setVisible(newVis2);
|
|
621
|
+
emitSync(newVis2);
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
if (result instanceof Promise) {
|
|
625
|
+
result.then(applyResult);
|
|
626
|
+
} else {
|
|
627
|
+
applyResult(result);
|
|
628
|
+
}
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
581
631
|
const cache = getCache(t.trigger);
|
|
582
632
|
const key = getItemKey(t, item);
|
|
583
633
|
cache.set(key, item);
|
|
@@ -655,7 +705,8 @@ function useMentionEngine(options) {
|
|
|
655
705
|
loadMore,
|
|
656
706
|
rawToVisible,
|
|
657
707
|
visibleToRaw,
|
|
658
|
-
caretPosRef
|
|
708
|
+
caretPosRef,
|
|
709
|
+
getItemForMention
|
|
659
710
|
};
|
|
660
711
|
}
|
|
661
712
|
function getItemKey(trigger, item) {
|
|
@@ -695,6 +746,7 @@ var MentionInput = forwardRef(({
|
|
|
695
746
|
highlighterClassName,
|
|
696
747
|
dropdownClassName,
|
|
697
748
|
dropdownWidth = 250,
|
|
749
|
+
loadingText,
|
|
698
750
|
renderDropdown,
|
|
699
751
|
"aria-label": ariaLabel,
|
|
700
752
|
"aria-describedby": ariaDescribedBy
|
|
@@ -767,6 +819,7 @@ var MentionInput = forwardRef(({
|
|
|
767
819
|
mentions: engine.mentions,
|
|
768
820
|
triggers,
|
|
769
821
|
textareaRef,
|
|
822
|
+
getItemForMention: engine.getItemForMention,
|
|
770
823
|
className: highlighterClassName,
|
|
771
824
|
style: SHARED_STYLE
|
|
772
825
|
}, undefined, false, undefined, this),
|
|
@@ -824,6 +877,7 @@ var MentionInput = forwardRef(({
|
|
|
824
877
|
onSelect: handleSelect,
|
|
825
878
|
onLoadMore: engine.searchHasMore ? engine.loadMore : undefined,
|
|
826
879
|
loading: engine.searchLoading,
|
|
880
|
+
loadingText,
|
|
827
881
|
position: dropdownPos,
|
|
828
882
|
width: dropdownWidth,
|
|
829
883
|
className: dropdownClassName
|
|
@@ -840,5 +894,5 @@ export {
|
|
|
840
894
|
MentionDropdown
|
|
841
895
|
};
|
|
842
896
|
|
|
843
|
-
//# debugId=
|
|
897
|
+
//# debugId=0811411863941EFA64756E2164756E21
|
|
844
898
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/MentionInput.tsx", "../../src/MentionDropdown.tsx", "../../src/MentionHighlighter.tsx", "../../src/useCaretPosition.ts", "../../src/useMentionEngine.ts", "../../src/utils.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { MentionDropdown } from \"./MentionDropdown.tsx\";\nimport { MentionHighlighter } from \"./MentionHighlighter.tsx\";\nimport type { CaretPosition, MentionInputProps } from \"./types.ts\";\nimport { useCaretPosition } from \"./useCaretPosition.ts\";\nimport { useMentionEngine } from \"./useMentionEngine.ts\";\n\nconst SHARED_STYLE: React.CSSProperties = {\n whiteSpace: \"pre-wrap\",\n overflowWrap: \"anywhere\",\n wordBreak: \"break-word\",\n padding: \"0.5rem 0.75rem\",\n fontFamily: \"inherit\",\n fontSize: \"inherit\",\n lineHeight: \"inherit\",\n letterSpacing: \"normal\",\n boxSizing: \"border-box\",\n};\n\nexport const MentionInput = forwardRef<HTMLTextAreaElement, MentionInputProps>(\n (\n {\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n placeholder,\n disabled,\n rows = 4,\n className,\n inputClassName,\n highlighterClassName,\n dropdownClassName,\n dropdownWidth = 250,\n renderDropdown,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n },\n ref\n ) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n useImperativeHandle(ref, () => textareaRef.current!);\n\n const engine = useMentionEngine({\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n });\n\n // Restore caret position after render, then clear so we don't\n // fight the browser on subsequent renders (like arrow-key navigation)\n useLayoutEffect(() => {\n const pos = engine.caretPosRef.current;\n const ta = textareaRef.current;\n if (pos !== null && ta && document.activeElement === ta) {\n ta.setSelectionRange(pos, pos);\n engine.caretPosRef.current = null;\n }\n });\n\n const { mirrorRef, getCaretPosition } = useCaretPosition(dropdownWidth);\n const [dropdownPos, setDropdownPos] = useState<CaretPosition | null>(null);\n\n // Update dropdown position when active trigger changes\n useEffect(() => {\n if (engine.activeTrigger && textareaRef.current) {\n requestAnimationFrame(() => {\n const pos = getCaretPosition(textareaRef.current!);\n if (pos) setDropdownPos(pos);\n });\n } else {\n setDropdownPos(null);\n }\n }, [engine.activeTrigger, engine.visible, getCaretPosition]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n engine.handleTextChange(e.target.value, e.target.selectionStart);\n },\n [engine.handleTextChange]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (textareaRef.current) {\n engine.handleKeyDown(e, textareaRef.current);\n }\n },\n [engine.handleKeyDown]\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const ta = textareaRef.current;\n if (!ta) return;\n const txt = e.clipboardData.getData(\"text\");\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n const newText =\n engine.visible.slice(0, start) + txt + engine.visible.slice(end);\n e.preventDefault();\n engine.handleTextChange(newText, start + txt.length);\n },\n [engine.visible, engine.handleTextChange]\n );\n\n const handleBlur = useCallback(() => {\n // delay allows dropdown click to fire first\n setTimeout(() => engine.closeSuggestions(), 150);\n }, [engine.closeSuggestions]);\n\n const handleSelect = useCallback(\n (item: unknown) => {\n if (textareaRef.current) {\n engine.selectOption(item, textareaRef.current);\n }\n },\n [engine.selectOption]\n );\n\n const showDropdown = engine.activeTrigger !== null && dropdownPos !== null;\n\n return (\n <div\n className={className}\n style={{ position: \"relative\" }}\n data-mentionize-container=\"\"\n >\n <MentionHighlighter\n visible={engine.visible}\n mentions={engine.mentions}\n triggers={triggers}\n textareaRef={textareaRef}\n className={highlighterClassName}\n style={SHARED_STYLE}\n />\n\n <textarea\n ref={textareaRef}\n value={engine.visible}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onBlur={handleBlur}\n rows={rows}\n placeholder={placeholder}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n aria-autocomplete=\"list\"\n aria-expanded={showDropdown}\n className={inputClassName}\n style={{\n ...SHARED_STYLE,\n position: \"relative\",\n width: \"100%\",\n resize: \"vertical\",\n background: \"transparent\",\n color: \"transparent\",\n caretColor: \"CanvasText\",\n zIndex: 10,\n }}\n data-mentionize-input=\"\"\n />\n\n {/* Caret mirror div */}\n <div\n ref={mirrorRef}\n aria-hidden\n style={{\n position: \"absolute\",\n top: 0,\n left: -9999,\n visibility: \"hidden\",\n ...SHARED_STYLE,\n }}\n data-mentionize-mirror=\"\"\n />\n\n {showDropdown && engine.activeTrigger && (\n renderDropdown ? (\n renderDropdown({\n items: engine.filteredOptions,\n highlightedIndex: engine.highlightIndex,\n onSelect: handleSelect,\n onHighlight: engine.setHighlightIndex,\n loading: engine.searchLoading,\n onLoadMore: engine.searchHasMore ? engine.loadMore : undefined,\n })\n ) : (\n <MentionDropdown\n items={engine.filteredOptions}\n trigger={engine.activeTrigger.trigger}\n highlightedIndex={engine.highlightIndex}\n onHighlight={engine.setHighlightIndex}\n onSelect={handleSelect}\n onLoadMore={engine.searchHasMore ? engine.loadMore : undefined}\n loading={engine.searchLoading}\n position={dropdownPos}\n width={dropdownWidth}\n className={dropdownClassName}\n />\n )\n )}\n </div>\n );\n }\n);\n\nMentionInput.displayName = \"MentionInput\";\n",
|
|
6
|
-
"import React, { useCallback, useEffect, useRef } from \"react\";\nimport type { CaretPosition, MentionTrigger } from \"./types.ts\";\n\ninterface MentionDropdownProps {\n items: unknown[];\n trigger: MentionTrigger<any>;\n highlightedIndex: number;\n onHighlight: (index: number) => void;\n onSelect: (item: unknown) => void;\n onLoadMore?: () => void;\n loading: boolean;\n position: CaretPosition;\n width: number;\n className?: string;\n}\n\nexport const MentionDropdown: React.FC<MentionDropdownProps> = ({\n items,\n trigger,\n highlightedIndex,\n onHighlight,\n onSelect,\n onLoadMore,\n loading,\n position,\n width,\n className,\n}) => {\n const listRef = useRef<HTMLDivElement>(null);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // IntersectionObserver for infinite scroll\n useEffect(() => {\n if (!onLoadMore || !sentinelRef.current) return;\n const sentinel = sentinelRef.current;\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0]?.isIntersecting) {\n onLoadMore();\n }\n },\n { root: listRef.current, threshold: 0.1 }\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [onLoadMore]);\n\n // Ensure highlighted item is visible\n useEffect(() => {\n const container = listRef.current;\n if (!container) return;\n const highlighted = container.querySelector(\n `[data-mentionize-option-index=\"${highlightedIndex}\"]`\n ) as HTMLElement | null;\n if (highlighted) {\n highlighted.scrollIntoView({ block: \"nearest\" });\n }\n }, [highlightedIndex]);\n\n // flip above if near bottom of viewport\n const maxHeight = 240;\n const gap = 4;\n const spaceBelow = window.innerHeight - position.top - gap;\n const flipAbove = spaceBelow < maxHeight && position.top > maxHeight;\n\n const style: React.CSSProperties = {\n position: \"fixed\",\n width,\n maxHeight,\n overflowY: \"auto\",\n zIndex: 50,\n ...(flipAbove\n ? { bottom: window.innerHeight - position.top + gap, left: position.left }\n : { top: position.top + gap, left: position.left }),\n };\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault(); // prevent blur of input\n }, []);\n\n if (!items.length && !loading) return null;\n\n return (\n <div\n ref={listRef}\n role=\"listbox\"\n className={className}\n style={style}\n data-mentionize-dropdown=\"\"\n onMouseDown={handleMouseDown}\n >\n {items.map((item, i) => {\n const isHighlighted = i === highlightedIndex;\n\n if (trigger.renderOption) {\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n data-mentionize-option-index={i}\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.renderOption(item, isHighlighted)}\n </div>\n );\n }\n\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n data-mentionize-option-index={i}\n data-mentionize-option=\"\"\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.displayText(item)}\n </div>\n );\n })}\n {loading && (\n <div data-mentionize-loading=\"\">Loading
|
|
7
|
-
"import React, { useEffect, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\n\ninterface MentionHighlighterProps {\n visible: string;\n mentions: ActiveMention[];\n triggers: MentionTrigger<any>[];\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/** Split a string so that newlines become <br/> elements */\nfunction textToNodes(text: string): React.ReactNode[] {\n const parts = text.split(\"\\n\");\n const nodes: React.ReactNode[] = [];\n for (let i = 0; i < parts.length; i++) {\n if (i > 0) nodes.push(React.createElement(\"br\", { key: `br-${i}` }));\n if (parts[i]) nodes.push(parts[i]);\n }\n return nodes;\n}\n\nexport const MentionHighlighter: React.FC<MentionHighlighterProps> = ({\n visible,\n mentions,\n triggers,\n textareaRef,\n className,\n style,\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n\n // Sync scroll with textarea\n useEffect(() => {\n const textarea = textareaRef.current;\n const highlighter = ref.current;\n if (!textarea || !highlighter) return;\n\n const onScroll = () => {\n highlighter.scrollTop = textarea.scrollTop;\n highlighter.scrollLeft = textarea.scrollLeft;\n };\n\n textarea.addEventListener(\"scroll\", onScroll);\n return () => textarea.removeEventListener(\"scroll\", onScroll);\n }, [textareaRef]);\n\n const children = useMemo(() => {\n const sorted = mentions.slice().sort((a, b) => a.start - b.start);\n if (!sorted.length) return textToNodes(visible);\n\n const
|
|
5
|
+
"import React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { MentionDropdown } from \"./MentionDropdown.tsx\";\nimport { MentionHighlighter } from \"./MentionHighlighter.tsx\";\nimport type { CaretPosition, MentionInputProps } from \"./types.ts\";\nimport { useCaretPosition } from \"./useCaretPosition.ts\";\nimport { useMentionEngine } from \"./useMentionEngine.ts\";\n\nconst SHARED_STYLE: React.CSSProperties = {\n whiteSpace: \"pre-wrap\",\n overflowWrap: \"anywhere\",\n wordBreak: \"break-word\",\n padding: \"0.5rem 0.75rem\",\n fontFamily: \"inherit\",\n fontSize: \"inherit\",\n lineHeight: \"inherit\",\n letterSpacing: \"normal\",\n boxSizing: \"border-box\",\n};\n\nexport const MentionInput = forwardRef<HTMLTextAreaElement, MentionInputProps>(\n (\n {\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n placeholder,\n disabled,\n rows = 4,\n className,\n inputClassName,\n highlighterClassName,\n dropdownClassName,\n dropdownWidth = 250,\n loadingText,\n renderDropdown,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n },\n ref\n ) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n useImperativeHandle(ref, () => textareaRef.current!);\n\n const engine = useMentionEngine({\n triggers,\n value,\n defaultValue,\n onChange,\n onMentionsChange,\n });\n\n // Restore caret position after render, then clear so we don't\n // fight the browser on subsequent renders (like arrow-key navigation)\n useLayoutEffect(() => {\n const pos = engine.caretPosRef.current;\n const ta = textareaRef.current;\n if (pos !== null && ta && document.activeElement === ta) {\n ta.setSelectionRange(pos, pos);\n engine.caretPosRef.current = null;\n }\n });\n\n const { mirrorRef, getCaretPosition } = useCaretPosition(dropdownWidth);\n const [dropdownPos, setDropdownPos] = useState<CaretPosition | null>(null);\n\n // Update dropdown position when active trigger changes\n useEffect(() => {\n if (engine.activeTrigger && textareaRef.current) {\n requestAnimationFrame(() => {\n const pos = getCaretPosition(textareaRef.current!);\n if (pos) setDropdownPos(pos);\n });\n } else {\n setDropdownPos(null);\n }\n }, [engine.activeTrigger, engine.visible, getCaretPosition]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n engine.handleTextChange(e.target.value, e.target.selectionStart);\n },\n [engine.handleTextChange]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (textareaRef.current) {\n engine.handleKeyDown(e, textareaRef.current);\n }\n },\n [engine.handleKeyDown]\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const ta = textareaRef.current;\n if (!ta) return;\n const txt = e.clipboardData.getData(\"text\");\n const start = ta.selectionStart;\n const end = ta.selectionEnd;\n const newText =\n engine.visible.slice(0, start) + txt + engine.visible.slice(end);\n e.preventDefault();\n engine.handleTextChange(newText, start + txt.length);\n },\n [engine.visible, engine.handleTextChange]\n );\n\n const handleBlur = useCallback(() => {\n // delay allows dropdown click to fire first\n setTimeout(() => engine.closeSuggestions(), 150);\n }, [engine.closeSuggestions]);\n\n const handleSelect = useCallback(\n (item: unknown) => {\n if (textareaRef.current) {\n engine.selectOption(item, textareaRef.current);\n }\n },\n [engine.selectOption]\n );\n\n const showDropdown = engine.activeTrigger !== null && dropdownPos !== null;\n\n return (\n <div\n className={className}\n style={{ position: \"relative\" }}\n data-mentionize-container=\"\"\n >\n <MentionHighlighter\n visible={engine.visible}\n mentions={engine.mentions}\n triggers={triggers}\n textareaRef={textareaRef}\n getItemForMention={engine.getItemForMention}\n className={highlighterClassName}\n style={SHARED_STYLE}\n />\n\n <textarea\n ref={textareaRef}\n value={engine.visible}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onBlur={handleBlur}\n rows={rows}\n placeholder={placeholder}\n disabled={disabled}\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n aria-autocomplete=\"list\"\n aria-expanded={showDropdown}\n className={inputClassName}\n style={{\n ...SHARED_STYLE,\n position: \"relative\",\n width: \"100%\",\n resize: \"vertical\",\n background: \"transparent\",\n color: \"transparent\",\n caretColor: \"CanvasText\",\n zIndex: 10,\n }}\n data-mentionize-input=\"\"\n />\n\n {/* Caret mirror div */}\n <div\n ref={mirrorRef}\n aria-hidden\n style={{\n position: \"absolute\",\n top: 0,\n left: -9999,\n visibility: \"hidden\",\n ...SHARED_STYLE,\n }}\n data-mentionize-mirror=\"\"\n />\n\n {showDropdown && engine.activeTrigger && (\n renderDropdown ? (\n renderDropdown({\n items: engine.filteredOptions,\n highlightedIndex: engine.highlightIndex,\n onSelect: handleSelect,\n onHighlight: engine.setHighlightIndex,\n loading: engine.searchLoading,\n onLoadMore: engine.searchHasMore ? engine.loadMore : undefined,\n })\n ) : (\n <MentionDropdown\n items={engine.filteredOptions}\n trigger={engine.activeTrigger.trigger}\n highlightedIndex={engine.highlightIndex}\n onHighlight={engine.setHighlightIndex}\n onSelect={handleSelect}\n onLoadMore={engine.searchHasMore ? engine.loadMore : undefined}\n loading={engine.searchLoading}\n loadingText={loadingText}\n position={dropdownPos}\n width={dropdownWidth}\n className={dropdownClassName}\n />\n )\n )}\n </div>\n );\n }\n);\n\nMentionInput.displayName = \"MentionInput\";\n",
|
|
6
|
+
"import React, { useCallback, useEffect, useRef } from \"react\";\nimport type { CaretPosition, MentionTrigger } from \"./types.ts\";\n\ninterface MentionDropdownProps {\n items: unknown[];\n trigger: MentionTrigger<any>;\n highlightedIndex: number;\n onHighlight: (index: number) => void;\n onSelect: (item: unknown) => void;\n onLoadMore?: () => void;\n loading: boolean;\n loadingText?: string;\n position: CaretPosition;\n width: number;\n className?: string;\n}\n\nexport const MentionDropdown: React.FC<MentionDropdownProps> = ({\n items,\n trigger,\n highlightedIndex,\n onHighlight,\n onSelect,\n onLoadMore,\n loading,\n loadingText,\n position,\n width,\n className,\n}) => {\n const listRef = useRef<HTMLDivElement>(null);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // IntersectionObserver for infinite scroll\n useEffect(() => {\n if (!onLoadMore || !sentinelRef.current) return;\n const sentinel = sentinelRef.current;\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0]?.isIntersecting) {\n onLoadMore();\n }\n },\n { root: listRef.current, threshold: 0.1 }\n );\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [onLoadMore]);\n\n // Ensure highlighted item is visible\n useEffect(() => {\n const container = listRef.current;\n if (!container) return;\n const highlighted = container.querySelector(\n `[data-mentionize-option-index=\"${highlightedIndex}\"]`\n ) as HTMLElement | null;\n if (highlighted) {\n highlighted.scrollIntoView({ block: \"nearest\" });\n }\n }, [highlightedIndex]);\n\n // flip above if near bottom of viewport\n const maxHeight = 240;\n const gap = 4;\n const spaceBelow = window.innerHeight - position.top - gap;\n const flipAbove = spaceBelow < maxHeight && position.top > maxHeight;\n\n const style: React.CSSProperties = {\n position: \"fixed\",\n width,\n maxHeight,\n overflowY: \"auto\",\n zIndex: 50,\n ...(flipAbove\n ? { bottom: window.innerHeight - position.top + gap, left: position.left }\n : { top: position.top + gap, left: position.left }),\n };\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault(); // prevent blur of input\n }, []);\n\n if (!items.length && !loading) return null;\n\n return (\n <div\n ref={listRef}\n role=\"listbox\"\n className={className}\n style={style}\n data-mentionize-dropdown=\"\"\n onMouseDown={handleMouseDown}\n >\n {items.map((item, i) => {\n const isHighlighted = i === highlightedIndex;\n const optCls = typeof trigger.optionClassName === \"function\"\n ? trigger.optionClassName(item)\n : trigger.optionClassName;\n\n if (trigger.renderOption) {\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n className={optCls}\n data-mentionize-option-index={i}\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.renderOption(item, isHighlighted)}\n </div>\n );\n }\n\n return (\n <div\n key={i}\n role=\"option\"\n aria-selected={isHighlighted}\n className={optCls}\n data-mentionize-option-index={i}\n data-mentionize-option=\"\"\n data-mentionize-option-highlighted={isHighlighted || undefined}\n onMouseEnter={() => onHighlight(i)}\n onClick={() => onSelect(item)}\n >\n {trigger.displayText(item)}\n </div>\n );\n })}\n {loading && (\n <div data-mentionize-loading=\"\">{loadingText ?? \"Loading...\"}</div>\n )}\n {onLoadMore && !loading && (\n <div ref={sentinelRef} style={{ height: 1 }} aria-hidden />\n )}\n </div>\n );\n};\n",
|
|
7
|
+
"import React, { useEffect, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\n\ninterface MentionHighlighterProps {\n visible: string;\n mentions: ActiveMention[];\n triggers: MentionTrigger<any>[];\n textareaRef: React.RefObject<HTMLTextAreaElement | null>;\n getItemForMention?: (triggerChar: string, key: string) => unknown;\n className?: string;\n style?: React.CSSProperties;\n}\n\n/** Split a string so that newlines become <br/> elements */\nfunction textToNodes(text: string): React.ReactNode[] {\n const parts = text.split(\"\\n\");\n const nodes: React.ReactNode[] = [];\n for (let i = 0; i < parts.length; i++) {\n if (i > 0) nodes.push(React.createElement(\"br\", { key: `br-${i}` }));\n if (parts[i]) nodes.push(parts[i]);\n }\n return nodes;\n}\n\nexport const MentionHighlighter: React.FC<MentionHighlighterProps> = ({\n visible,\n mentions,\n triggers,\n textareaRef,\n getItemForMention,\n className,\n style,\n}) => {\n const ref = useRef<HTMLDivElement>(null);\n\n // Sync scroll with textarea\n useEffect(() => {\n const textarea = textareaRef.current;\n const highlighter = ref.current;\n if (!textarea || !highlighter) return;\n\n const onScroll = () => {\n highlighter.scrollTop = textarea.scrollTop;\n highlighter.scrollLeft = textarea.scrollLeft;\n };\n\n textarea.addEventListener(\"scroll\", onScroll);\n return () => textarea.removeEventListener(\"scroll\", onScroll);\n }, [textareaRef]);\n\n const children = useMemo(() => {\n const sorted = mentions.slice().sort((a, b) => a.start - b.start);\n if (!sorted.length) return textToNodes(visible);\n\n const triggerMap = new Map<string, MentionTrigger<any>>();\n for (const t of triggers) {\n triggerMap.set(t.trigger, t);\n }\n\n const nodes: React.ReactNode[] = [];\n let last = 0;\n for (let i = 0; i < sorted.length; i++) {\n const m = sorted[i]!;\n // Text before this mention\n if (last < m.start) {\n nodes.push(...textToNodes(visible.slice(last, m.start)));\n }\n\n const mentionText = visible.slice(m.start, m.end);\n const t = triggerMap.get(m.trigger);\n let cls = \"mentionize-mention\";\n if (t) {\n if (typeof t.mentionClassName === \"function\") {\n const item = getItemForMention?.(m.trigger, m.key) ?? null;\n cls = t.mentionClassName({\n key: m.key,\n displayText: m.displayText,\n trigger: m.trigger,\n item,\n });\n } else if (t.mentionClassName) {\n cls = t.mentionClassName;\n }\n }\n nodes.push(\n React.createElement(\n \"span\",\n {\n key: `mention-${i}`,\n className: cls,\n \"data-mentionize-trigger\": m.trigger,\n \"data-mentionize-key\": m.key,\n },\n mentionText\n )\n );\n last = m.end;\n }\n // after last mention\n if (last < visible.length) {\n nodes.push(...textToNodes(visible.slice(last)));\n }\n return nodes;\n }, [visible, mentions, triggers, getItemForMention]);\n\n // After render, neutralize horizontal box-model impact of mention spans\n // so user-applied padding/border/margin don't shift overlay text relative to the textarea.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n const spans = el.querySelectorAll<HTMLElement>(\"[data-mentionize-trigger]\");\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i]!;\n // Reset any previous compensation before measuring\n span.style.marginLeft = \"\";\n span.style.marginRight = \"\";\n const cs = getComputedStyle(span);\n const extraLeft =\n parseFloat(cs.paddingLeft) +\n parseFloat(cs.borderLeftWidth) +\n parseFloat(cs.marginLeft);\n const extraRight =\n parseFloat(cs.paddingRight) +\n parseFloat(cs.borderRightWidth) +\n parseFloat(cs.marginRight);\n if (extraLeft) span.style.marginLeft = `${-extraLeft}px`;\n if (extraRight) span.style.marginRight = `${-extraRight}px`;\n }\n });\n\n return React.createElement(\n \"div\",\n {\n ref,\n className,\n style: {\n position: \"absolute\" as const,\n inset: 0,\n pointerEvents: \"none\" as const,\n overflow: \"auto\",\n ...style,\n },\n \"aria-hidden\": true,\n \"data-mentionize-highlighter\": \"\",\n },\n ...children\n );\n};\n",
|
|
8
8
|
"import { useCallback, useRef } from \"react\";\nimport type { CaretPosition } from \"./types.ts\";\n\nconst SHARED_STYLE_PROPS = [\n \"whiteSpace\",\n \"overflowWrap\",\n \"wordBreak\",\n \"padding\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"fontFamily\",\n \"fontSize\",\n \"fontWeight\",\n \"lineHeight\",\n \"letterSpacing\",\n \"tabSize\",\n \"boxSizing\",\n \"borderWidth\",\n \"borderStyle\",\n] as const;\n\nexport function useCaretPosition(dropdownWidth: number) {\n const mirrorRef = useRef<HTMLDivElement>(null);\n\n const getCaretPosition = useCallback(\n (\n textarea: HTMLTextAreaElement,\n caretIndex?: number,\n textOverride?: string\n ): CaretPosition | null => {\n const mirror = mirrorRef.current;\n if (!mirror) return null;\n\n const caret = caretIndex ?? textarea.selectionStart;\n const source = textOverride ?? textarea.value;\n const before = source.slice(0, caret);\n\n // Copy textarea computed styles to mirror\n const computed = getComputedStyle(textarea);\n for (const prop of SHARED_STYLE_PROPS) {\n (mirror.style as any)[prop] = (computed as any)[prop];\n }\n mirror.style.width = `${textarea.offsetWidth}px`;\n\n mirror.textContent = before;\n\n const span = document.createElement(\"span\");\n span.textContent = \"\\u200b\";\n mirror.appendChild(span);\n mirror.scrollTop = textarea.scrollTop;\n\n const spanRect = span.getBoundingClientRect();\n const mirrorRect = mirror.getBoundingClientRect();\n const textareaRect = textarea.getBoundingClientRect();\n\n const top =\n textareaRect.top +\n (spanRect.top - mirrorRect.top) -\n textarea.scrollTop +\n span.offsetHeight;\n let left = textareaRect.left + (spanRect.left - mirrorRect.left);\n\n // Clamp to viewport\n if (left + dropdownWidth > window.innerWidth - 8) {\n left = window.innerWidth - dropdownWidth - 8;\n }\n if (left < 8) left = 8;\n\n mirror.innerHTML = \"\";\n\n return {\n top: Math.min(Math.max(top, 8), window.innerHeight - 8),\n left,\n };\n },\n [dropdownWidth]\n );\n\n return { mirrorRef, getCaretPosition };\n}\n",
|
|
9
|
-
"import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\nimport { escapeRegex } from \"./utils.ts\";\n\ninterface ActiveTriggerState {\n trigger: MentionTrigger<any>;\n query: string;\n startPos: number; // where the trigger character is in the visible text\n}\n\ninterface SearchState {\n items: unknown[];\n page: number;\n hasMore: boolean;\n loading: boolean;\n}\n\ninterface MentionEngineOptions {\n triggers: MentionTrigger<any>[];\n value?: string;\n defaultValue?: string;\n onChange?: (raw: string) => void;\n onMentionsChange?: (mentions: ActiveMention[]) => void;\n}\n\n// Detect mentions in visible text\nfunction detectMentionsInText(\n visibleText: string,\n triggers: MentionTrigger<any>[],\n getCache: (triggerChar: string) => Map<string, unknown>,\n): ActiveMention[] {\n const all: ActiveMention[] = [];\n\n for (const t of triggers) {\n const triggerChar = t.trigger;\n if (!visibleText.includes(triggerChar)) continue;\n\n const cache = getCache(triggerChar);\n const knownItems: { displayText: string; key: string; item: unknown }[] =\n [];\n\n if (t.options) {\n for (const item of t.options) {\n knownItems.push({\n displayText: t.displayText(item),\n key: getItemKey(t, item),\n item,\n });\n }\n }\n\n for (const [key, item] of cache.entries()) {\n if (item !== null) {\n const dt = t.displayText(item);\n if (!knownItems.some((k) => k.key === key)) {\n knownItems.push({ displayText: dt, key, item });\n }\n }\n }\n\n if (!knownItems.length) continue;\n\n const compiled = knownItems.map((ki) => {\n const pat = \"^\" + escapeRegex(ki.displayText).replace(/\\s+/g, \"\\\\s+\");\n return { ...ki, re: new RegExp(pat, \"i\") };\n });\n\n const positions: number[] = [];\n let idx = visibleText.indexOf(triggerChar);\n while (idx !== -1) {\n positions.push(idx);\n idx = visibleText.indexOf(triggerChar, idx + 1);\n }\n\n const candidates: ActiveMention[] = [];\n for (const pos of positions) {\n const after = visibleText.slice(pos + triggerChar.length);\n for (const c of compiled) {\n const match = c.re.exec(after);\n if (!match) continue;\n const matched = match[0];\n const end = pos + triggerChar.length + matched.length;\n const next = visibleText[end];\n if (next && !/[\\s,.:;!?)}\\]]/.test(next)) continue;\n candidates.push({\n trigger: triggerChar,\n displayText: matched,\n key: c.key,\n start: pos,\n end,\n });\n }\n }\n\n candidates.sort((a, b) =>\n a.start !== b.start\n ? a.start - b.start\n : b.end - b.start - (a.end - a.start),\n );\n for (const c of candidates) {\n const overlaps = all.some(\n (f) => Math.max(f.start, c.start) < Math.min(f.end, c.end),\n );\n if (!overlaps) all.push(c);\n }\n }\n\n return all;\n}\n\n// Shallow-compare two mention arrays\nfunction mentionsEqual(a: ActiveMention[], b: ActiveMention[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i]!;\n const bi = b[i]!;\n if (ai.start !== bi.start || ai.end !== bi.end || ai.key !== bi.key)\n return false;\n }\n return true;\n}\n\nexport function useMentionEngine(options: MentionEngineOptions) {\n const {\n triggers,\n value: controlledValue,\n defaultValue,\n onChange,\n onMentionsChange,\n } = options;\n\n const lastRawRef = useRef(controlledValue ?? defaultValue ?? \"\");\n const suppressEmitRef = useRef(false);\n const caretPosRef = useRef<number | null>(null);\n const prevMentionsRef = useRef<ActiveMention[]>([]);\n\n // Known items cache\n const cacheRef = useRef<Map<string, Map<string, unknown>>>(new Map());\n\n function getCache(triggerChar: string): Map<string, unknown> {\n let map = cacheRef.current.get(triggerChar);\n if (!map) {\n map = new Map();\n cacheRef.current.set(triggerChar, map);\n }\n return map;\n }\n\n // Populate cache from static options\n useEffect(() => {\n for (const t of triggers) {\n if (t.options) {\n const cache = getCache(t.trigger);\n for (const item of t.options) {\n const serialized = t.serialize(item);\n // Extract key by running pattern on the serialized form\n const re = new RegExp(\n t.pattern.source,\n t.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n const { key } = t.parseMatch(m);\n cache.set(key, item);\n }\n }\n }\n }\n }, [triggers]);\n\n // Convert raw to visible text\n const rawToVisible = useCallback(\n (raw: string): string => {\n let result = raw;\n for (const t of triggers) {\n const globalRe = new RegExp(\n t.pattern.source,\n t.pattern.flags.includes(\"g\")\n ? t.pattern.flags\n : t.pattern.flags + \"g\",\n );\n const parts: string[] = [];\n let lastIndex = 0;\n let m: RegExpExecArray | null;\n globalRe.lastIndex = 0;\n while ((m = globalRe.exec(result)) !== null) {\n parts.push(result.slice(lastIndex, m.index));\n const parsed = t.parseMatch(m);\n // Cache the item data from the match\n const cache = getCache(t.trigger);\n // placeholder for unmatched items\n if (!cache.has(parsed.key)) {\n cache.set(parsed.key, null);\n }\n parts.push(t.trigger + parsed.displayText);\n lastIndex = m.index + m[0].length;\n if (!t.pattern.flags.includes(\"g\")) break;\n }\n parts.push(result.slice(lastIndex));\n result = parts.join(\"\");\n }\n return result;\n },\n [triggers],\n );\n\n // Initialize visible text from raw\n const [visible, setVisible] = useState<string>(() =>\n rawToVisible(controlledValue ?? defaultValue ?? \"\"),\n );\n\n // Detect mentions in visible text\n const mentions: ActiveMention[] = useMemo(() => {\n const newMentions = detectMentionsInText(visible, triggers, getCache);\n if (mentionsEqual(prevMentionsRef.current, newMentions)) {\n return prevMentionsRef.current;\n }\n prevMentionsRef.current = newMentions;\n return newMentions;\n }, [visible, triggers]);\n\n // Build raw value from visible + mentions\n const visibleToRaw = useCallback(\n (vis: string, mentionsList: ActiveMention[]): string => {\n if (!mentionsList.length) return vis;\n const ordered = mentionsList.slice().sort((a, b) => a.start - b.start);\n let raw = \"\";\n let last = 0;\n for (const m of ordered) {\n raw += vis.slice(last, m.start);\n // Find the trigger config and the cached item\n const t = triggers.find((tr) => tr.trigger === m.trigger);\n if (t) {\n const cache = getCache(t.trigger);\n const item = cache.get(m.key);\n if (item !== null && item !== undefined) {\n raw += t.serialize(item);\n } else {\n raw += vis.slice(m.start, m.end);\n }\n } else {\n raw += vis.slice(m.start, m.end);\n }\n last = m.end;\n }\n raw += vis.slice(last);\n return raw;\n },\n [triggers],\n );\n\n // Synchronously emit raw value + mentions after visible text changes\n const emitSync = useCallback(\n (newVisible: string) => {\n const newMentions = detectMentionsInText(newVisible, triggers, getCache);\n\n if (!mentionsEqual(prevMentionsRef.current, newMentions)) {\n prevMentionsRef.current = newMentions;\n }\n\n const raw = visibleToRaw(newVisible, prevMentionsRef.current);\n if (raw !== lastRawRef.current) {\n lastRawRef.current = raw;\n onChange?.(raw);\n }\n onMentionsChange?.(prevMentionsRef.current);\n },\n [triggers, visibleToRaw, onChange, onMentionsChange],\n );\n\n useEffect(() => {\n if (controlledValue === undefined) return;\n if (controlledValue === lastRawRef.current) return;\n lastRawRef.current = controlledValue;\n suppressEmitRef.current = true;\n setVisible(rawToVisible(controlledValue));\n }, [controlledValue, rawToVisible]);\n\n const [activeTrigger, setActiveTrigger] = useState<ActiveTriggerState | null>(\n null,\n );\n const [searchState, setSearchState] = useState<SearchState>({\n items: [],\n page: 0,\n hasMore: false,\n loading: false,\n });\n const [highlightIndex, setHighlightIndex] = useState(0);\n const searchAbortRef = useRef<AbortController | null>(null);\n\n const detectActiveTrigger = useCallback(\n (text: string, caretPos: number): ActiveTriggerState | null => {\n // Look backwards from caret for any trigger character\n const prefix = text.slice(0, caretPos);\n for (const t of triggers) {\n const triggerChar = t.trigger;\n // Find the last occurrence of trigger char before caret\n const re = new RegExp(\n escapeRegex(triggerChar) +\n \"([^\\\\n\" +\n escapeRegex(triggerChar) +\n \"]*)$\",\n );\n const match = re.exec(prefix);\n if (match && match[1] !== undefined) {\n const query = match[1];\n // Don't activate if query contains whitespace (user moved on)\n if (/\\s/.test(query)) continue;\n return {\n trigger: t,\n query,\n startPos: match.index,\n };\n }\n }\n return null;\n },\n [triggers],\n );\n\n // Get filtered options for current trigger\n const filteredOptions = useMemo(() => {\n if (!activeTrigger) return [];\n const t = activeTrigger.trigger;\n const q = activeTrigger.query.toLowerCase();\n\n if (t.onSearch) {\n // Async mode returns search state items\n return searchState.items;\n }\n\n if (t.options) {\n if (!q) return t.options;\n return t.options.filter((item) =>\n t.displayText(item).toLowerCase().includes(q),\n );\n }\n\n return [];\n }, [activeTrigger, searchState.items]);\n\n useEffect(() => {\n if (!activeTrigger?.trigger.onSearch) return;\n\n const t = activeTrigger.trigger;\n const query = activeTrigger.query;\n\n // Abort previous search\n searchAbortRef.current?.abort();\n const controller = new AbortController();\n searchAbortRef.current = controller;\n\n setSearchState((s) => ({ ...s, loading: true, page: 0 }));\n\n const timer = setTimeout(async () => {\n try {\n const result = await t.onSearch!(query, 0);\n if (controller.signal.aborted) return;\n setSearchState({\n items: result.items,\n page: 0,\n hasMore: result.hasMore,\n loading: false,\n });\n } catch {\n if (controller.signal.aborted) return;\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, 150);\n\n return () => {\n clearTimeout(timer);\n controller.abort();\n };\n }, [activeTrigger?.trigger, activeTrigger?.query]);\n\n const loadMore = useCallback(async () => {\n if (\n !activeTrigger?.trigger.onSearch ||\n searchState.loading ||\n !searchState.hasMore\n )\n return;\n\n const t = activeTrigger.trigger;\n const nextPage = searchState.page + 1;\n setSearchState((s) => ({ ...s, loading: true }));\n\n try {\n const result = await t.onSearch!(activeTrigger.query, nextPage);\n setSearchState((s) => ({\n items: [...s.items, ...result.items],\n page: nextPage,\n hasMore: result.hasMore,\n loading: false,\n }));\n } catch {\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, [activeTrigger, searchState]);\n\n // Handle text change from textarea\n const handleTextChange = useCallback(\n (newText: string, caretPos: number) => {\n caretPosRef.current = caretPos;\n setVisible(newText);\n emitSync(newText);\n const detected = detectActiveTrigger(newText, caretPos);\n if (detected) {\n setActiveTrigger(detected);\n setHighlightIndex(0);\n } else {\n setActiveTrigger(null);\n }\n },\n [detectActiveTrigger, emitSync],\n );\n\n // Select an option from the dropdown\n const selectOption = useCallback(\n (item: unknown, textarea: HTMLTextAreaElement) => {\n if (!activeTrigger) return;\n const t = activeTrigger.trigger;\n\n // Add to cache\n const cache = getCache(t.trigger);\n const key = getItemKey(t, item);\n cache.set(key, item);\n\n const displayText = t.displayText(item);\n const mentionText = t.trigger + displayText;\n\n const before = visible.slice(0, activeTrigger.startPos);\n const after = visible.slice(textarea.selectionStart);\n const newVis = before + mentionText + \" \" + after;\n\n const pos = before.length + mentionText.length + 1;\n caretPosRef.current = pos;\n setVisible(newVis);\n emitSync(newVis);\n setActiveTrigger(null);\n },\n [activeTrigger, visible, emitSync],\n );\n\n const closeSuggestions = useCallback(() => {\n setActiveTrigger(null);\n setSearchState({ items: [], page: 0, hasMore: false, loading: false });\n }, []);\n\n // Keyboard handling\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, textarea: HTMLTextAreaElement): boolean => {\n if (!activeTrigger) return false;\n\n const len = filteredOptions.length;\n if (!len && !searchState.loading) return false;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n const next = (highlightIndex + 1) % Math.max(len, 1);\n setHighlightIndex(next);\n // Trigger load more near end\n if (\n len - 1 - next <= 3 &&\n searchState.hasMore &&\n !searchState.loading\n ) {\n loadMore();\n }\n return true;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setHighlightIndex(\n (highlightIndex - 1 + Math.max(len, 1)) % Math.max(len, 1),\n );\n return true;\n }\n if (e.key === \"Enter\") {\n e.preventDefault();\n const item = filteredOptions[highlightIndex];\n if (item) selectOption(item, textarea);\n return true;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n closeSuggestions();\n return true;\n }\n return false;\n },\n [\n activeTrigger,\n filteredOptions,\n highlightIndex,\n searchState,\n selectOption,\n closeSuggestions,\n loadMore,\n ],\n );\n\n return {\n visible,\n setVisible,\n mentions,\n activeTrigger,\n filteredOptions,\n highlightIndex,\n setHighlightIndex,\n searchLoading: searchState.loading,\n searchHasMore: searchState.hasMore,\n handleTextChange,\n handleKeyDown,\n selectOption,\n closeSuggestions,\n loadMore,\n rawToVisible,\n visibleToRaw,\n caretPosRef,\n };\n}\n\nfunction getItemKey(trigger: MentionTrigger<any>, item: unknown): string {\n const serialized = trigger.serialize(item);\n const re = new RegExp(\n trigger.pattern.source,\n trigger.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n return trigger.parseMatch(m).key;\n }\n return serialized;\n}\n",
|
|
9
|
+
"import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ActiveMention, MentionTrigger } from \"./types.ts\";\nimport { escapeRegex } from \"./utils.ts\";\n\ninterface ActiveTriggerState {\n trigger: MentionTrigger<any>;\n query: string;\n startPos: number; // where the trigger character is in the visible text\n}\n\ninterface SearchState {\n items: unknown[];\n page: number;\n hasMore: boolean;\n loading: boolean;\n}\n\ninterface MentionEngineOptions {\n triggers: MentionTrigger<any>[];\n value?: string;\n defaultValue?: string;\n onChange?: (raw: string) => void;\n onMentionsChange?: (mentions: ActiveMention[]) => void;\n}\n\n// Detect mentions in visible text\nfunction detectMentionsInText(\n visibleText: string,\n triggers: MentionTrigger<any>[],\n getCache: (triggerChar: string) => Map<string, unknown>,\n): ActiveMention[] {\n const all: ActiveMention[] = [];\n\n for (const t of triggers) {\n const triggerChar = t.trigger;\n if (!visibleText.includes(triggerChar)) continue;\n\n const cache = getCache(triggerChar);\n const knownItems: { displayText: string; key: string; item: unknown }[] =\n [];\n\n if (t.options) {\n for (const item of t.options) {\n knownItems.push({\n displayText: t.displayText(item),\n key: getItemKey(t, item),\n item,\n });\n }\n }\n\n for (const [key, item] of cache.entries()) {\n if (item !== null) {\n const dt = t.displayText(item);\n if (!knownItems.some((k) => k.key === key)) {\n knownItems.push({ displayText: dt, key, item });\n }\n }\n }\n\n if (!knownItems.length) continue;\n\n const compiled = knownItems.map((ki) => {\n const pat = \"^\" + escapeRegex(ki.displayText).replace(/\\s+/g, \"\\\\s+\");\n return { ...ki, re: new RegExp(pat, \"i\") };\n });\n\n const positions: number[] = [];\n let idx = visibleText.indexOf(triggerChar);\n while (idx !== -1) {\n positions.push(idx);\n idx = visibleText.indexOf(triggerChar, idx + 1);\n }\n\n const candidates: ActiveMention[] = [];\n for (const pos of positions) {\n const after = visibleText.slice(pos + triggerChar.length);\n for (const c of compiled) {\n const match = c.re.exec(after);\n if (!match) continue;\n const matched = match[0];\n const end = pos + triggerChar.length + matched.length;\n const next = visibleText[end];\n if (next && !/[\\s,.:;!?)}\\]]/.test(next)) continue;\n candidates.push({\n trigger: triggerChar,\n displayText: matched,\n key: c.key,\n start: pos,\n end,\n });\n }\n }\n\n candidates.sort((a, b) =>\n a.start !== b.start\n ? a.start - b.start\n : b.end - b.start - (a.end - a.start),\n );\n for (const c of candidates) {\n const overlaps = all.some(\n (f) => Math.max(f.start, c.start) < Math.min(f.end, c.end),\n );\n if (!overlaps) all.push(c);\n }\n }\n\n return all;\n}\n\n// Shallow-compare two mention arrays\nfunction mentionsEqual(a: ActiveMention[], b: ActiveMention[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n const ai = a[i]!;\n const bi = b[i]!;\n if (ai.start !== bi.start || ai.end !== bi.end || ai.key !== bi.key)\n return false;\n }\n return true;\n}\n\nexport function useMentionEngine(options: MentionEngineOptions) {\n const {\n triggers,\n value: controlledValue,\n defaultValue,\n onChange,\n onMentionsChange,\n } = options;\n\n const lastRawRef = useRef(controlledValue ?? defaultValue ?? \"\");\n const suppressEmitRef = useRef(false);\n const caretPosRef = useRef<number | null>(null);\n const prevMentionsRef = useRef<ActiveMention[]>([]);\n\n // Known items cache\n const cacheRef = useRef<Map<string, Map<string, unknown>>>(new Map());\n\n function getCache(triggerChar: string): Map<string, unknown> {\n let map = cacheRef.current.get(triggerChar);\n if (!map) {\n map = new Map();\n cacheRef.current.set(triggerChar, map);\n }\n return map;\n }\n\n // Populate cache from static options\n useEffect(() => {\n for (const t of triggers) {\n if (t.options) {\n const cache = getCache(t.trigger);\n for (const item of t.options) {\n const serialized = t.serialize(item);\n // Extract key by running pattern on the serialized form\n const re = new RegExp(\n t.pattern.source,\n t.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n const { key } = t.parseMatch(m);\n cache.set(key, item);\n }\n }\n }\n }\n }, [triggers]);\n\n // Convert raw to visible text\n const rawToVisible = useCallback(\n (raw: string): string => {\n let result = raw;\n for (const t of triggers) {\n const globalRe = new RegExp(\n t.pattern.source,\n t.pattern.flags.includes(\"g\")\n ? t.pattern.flags\n : t.pattern.flags + \"g\",\n );\n const parts: string[] = [];\n let lastIndex = 0;\n let m: RegExpExecArray | null;\n globalRe.lastIndex = 0;\n while ((m = globalRe.exec(result)) !== null) {\n parts.push(result.slice(lastIndex, m.index));\n const parsed = t.parseMatch(m);\n // Cache the item data from the match\n const cache = getCache(t.trigger);\n // placeholder for unmatched items\n if (!cache.has(parsed.key)) {\n cache.set(parsed.key, null);\n }\n parts.push(t.trigger + parsed.displayText);\n lastIndex = m.index + m[0].length;\n if (!t.pattern.flags.includes(\"g\")) break;\n }\n parts.push(result.slice(lastIndex));\n result = parts.join(\"\");\n }\n return result;\n },\n [triggers],\n );\n\n // Initialize visible text from raw\n const [visible, setVisible] = useState<string>(() =>\n rawToVisible(controlledValue ?? defaultValue ?? \"\"),\n );\n\n // Detect mentions in visible text\n const mentions: ActiveMention[] = useMemo(() => {\n const newMentions = detectMentionsInText(visible, triggers, getCache);\n if (mentionsEqual(prevMentionsRef.current, newMentions)) {\n return prevMentionsRef.current;\n }\n prevMentionsRef.current = newMentions;\n return newMentions;\n }, [visible, triggers]);\n\n // Build raw value from visible + mentions\n const visibleToRaw = useCallback(\n (vis: string, mentionsList: ActiveMention[]): string => {\n if (!mentionsList.length) return vis;\n const ordered = mentionsList.slice().sort((a, b) => a.start - b.start);\n let raw = \"\";\n let last = 0;\n for (const m of ordered) {\n raw += vis.slice(last, m.start);\n // Find the trigger config and the cached item\n const t = triggers.find((tr) => tr.trigger === m.trigger);\n if (t) {\n const cache = getCache(t.trigger);\n const item = cache.get(m.key);\n if (item !== null && item !== undefined) {\n raw += t.serialize(item);\n } else {\n raw += vis.slice(m.start, m.end);\n }\n } else {\n raw += vis.slice(m.start, m.end);\n }\n last = m.end;\n }\n raw += vis.slice(last);\n return raw;\n },\n [triggers],\n );\n\n // Synchronously emit raw value + mentions after visible text changes\n const emitSync = useCallback(\n (newVisible: string) => {\n const newMentions = detectMentionsInText(newVisible, triggers, getCache);\n\n if (!mentionsEqual(prevMentionsRef.current, newMentions)) {\n prevMentionsRef.current = newMentions;\n }\n\n const raw = visibleToRaw(newVisible, prevMentionsRef.current);\n if (raw !== lastRawRef.current) {\n lastRawRef.current = raw;\n onChange?.(raw);\n }\n onMentionsChange?.(prevMentionsRef.current);\n },\n [triggers, visibleToRaw, onChange, onMentionsChange],\n );\n\n useEffect(() => {\n if (controlledValue === undefined) return;\n if (controlledValue === lastRawRef.current) return;\n lastRawRef.current = controlledValue;\n suppressEmitRef.current = true;\n setVisible(rawToVisible(controlledValue));\n }, [controlledValue, rawToVisible]);\n\n const [activeTrigger, setActiveTrigger] = useState<ActiveTriggerState | null>(\n null,\n );\n const [searchState, setSearchState] = useState<SearchState>({\n items: [],\n page: 0,\n hasMore: false,\n loading: false,\n });\n const [highlightIndex, setHighlightIndex] = useState(0);\n const searchAbortRef = useRef<AbortController | null>(null);\n\n const detectActiveTrigger = useCallback(\n (text: string, caretPos: number): ActiveTriggerState | null => {\n // Look backwards from caret for any trigger character\n const prefix = text.slice(0, caretPos);\n for (const t of triggers) {\n const triggerChar = t.trigger;\n // Find the last occurrence of trigger char before caret\n const re = new RegExp(\n escapeRegex(triggerChar) +\n \"([^\\\\n\" +\n escapeRegex(triggerChar) +\n \"]*)$\",\n );\n const match = re.exec(prefix);\n if (match && match[1] !== undefined) {\n const query = match[1];\n // Don't activate if query contains whitespace (user moved on)\n if (/\\s/.test(query)) continue;\n return {\n trigger: t,\n query,\n startPos: match.index,\n };\n }\n }\n return null;\n },\n [triggers],\n );\n\n // Get filtered options for current trigger\n const filteredOptions = useMemo(() => {\n if (!activeTrigger) return [];\n const t = activeTrigger.trigger;\n const q = activeTrigger.query.toLowerCase();\n\n if (t.onSearch) {\n // Async mode returns search state items\n return searchState.items;\n }\n\n if (t.options) {\n if (!q) return t.options;\n return t.options.filter((item) =>\n t.displayText(item).toLowerCase().includes(q),\n );\n }\n\n return [];\n }, [activeTrigger, searchState.items]);\n\n useEffect(() => {\n if (!activeTrigger?.trigger.onSearch) return;\n\n const t = activeTrigger.trigger;\n const query = activeTrigger.query;\n\n // Abort previous search\n searchAbortRef.current?.abort();\n const controller = new AbortController();\n searchAbortRef.current = controller;\n\n setSearchState((s) => ({ ...s, loading: true, page: 0 }));\n\n const timer = setTimeout(async () => {\n try {\n const result = await t.onSearch!(query, 0);\n if (controller.signal.aborted) return;\n setSearchState({\n items: result.items,\n page: 0,\n hasMore: result.hasMore,\n loading: false,\n });\n } catch {\n if (controller.signal.aborted) return;\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, 150);\n\n return () => {\n clearTimeout(timer);\n controller.abort();\n };\n }, [activeTrigger?.trigger, activeTrigger?.query]);\n\n const loadMore = useCallback(async () => {\n if (\n !activeTrigger?.trigger.onSearch ||\n searchState.loading ||\n !searchState.hasMore\n )\n return;\n\n const t = activeTrigger.trigger;\n const nextPage = searchState.page + 1;\n setSearchState((s) => ({ ...s, loading: true }));\n\n try {\n const result = await t.onSearch!(activeTrigger.query, nextPage);\n setSearchState((s) => ({\n items: [...s.items, ...result.items],\n page: nextPage,\n hasMore: result.hasMore,\n loading: false,\n }));\n } catch {\n setSearchState((s) => ({ ...s, loading: false }));\n }\n }, [activeTrigger, searchState]);\n\n // Handle text change from textarea\n const handleTextChange = useCallback(\n (newText: string, caretPos: number) => {\n caretPosRef.current = caretPos;\n setVisible(newText);\n emitSync(newText);\n const detected = detectActiveTrigger(newText, caretPos);\n if (detected) {\n setActiveTrigger(detected);\n setHighlightIndex(0);\n } else {\n setActiveTrigger(null);\n }\n },\n [detectActiveTrigger, emitSync],\n );\n\n // Look up a cached item for a mention\n const getItemForMention = useCallback(\n (triggerChar: string, key: string): unknown => {\n const cache = getCache(triggerChar);\n return cache.get(key) ?? null;\n },\n [],\n );\n\n // Select an option from the dropdown\n const selectOption = useCallback(\n (item: unknown, textarea: HTMLTextAreaElement) => {\n if (!activeTrigger) return;\n const t = activeTrigger.trigger;\n\n if (t.onSelect) {\n // Action trigger mode: close dropdown, remove trigger+query, call onSelect\n const before = visible.slice(0, activeTrigger.startPos);\n const after = visible.slice(textarea.selectionStart);\n const savedStartPos = activeTrigger.startPos;\n\n setActiveTrigger(null);\n\n const result = t.onSelect(item);\n const applyResult = (value: string | null) => {\n if (value !== null) {\n const newVis = before + value + after;\n const pos = savedStartPos + value.length;\n caretPosRef.current = pos;\n setVisible(newVis);\n emitSync(newVis);\n } else {\n // null = cancel, just remove the trigger+query\n const newVis = before + after;\n caretPosRef.current = savedStartPos;\n setVisible(newVis);\n emitSync(newVis);\n }\n };\n\n if (result instanceof Promise) {\n result.then(applyResult);\n } else {\n applyResult(result);\n }\n return;\n }\n\n // Standard mention mode\n const cache = getCache(t.trigger);\n const key = getItemKey(t, item);\n cache.set(key, item);\n\n const displayText = t.displayText(item);\n const mentionText = t.trigger + displayText;\n\n const before = visible.slice(0, activeTrigger.startPos);\n const after = visible.slice(textarea.selectionStart);\n const newVis = before + mentionText + \" \" + after;\n\n const pos = before.length + mentionText.length + 1;\n caretPosRef.current = pos;\n setVisible(newVis);\n emitSync(newVis);\n setActiveTrigger(null);\n },\n [activeTrigger, visible, emitSync],\n );\n\n const closeSuggestions = useCallback(() => {\n setActiveTrigger(null);\n setSearchState({ items: [], page: 0, hasMore: false, loading: false });\n }, []);\n\n // Keyboard handling\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, textarea: HTMLTextAreaElement): boolean => {\n if (!activeTrigger) return false;\n\n const len = filteredOptions.length;\n if (!len && !searchState.loading) return false;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n const next = (highlightIndex + 1) % Math.max(len, 1);\n setHighlightIndex(next);\n // Trigger load more near end\n if (\n len - 1 - next <= 3 &&\n searchState.hasMore &&\n !searchState.loading\n ) {\n loadMore();\n }\n return true;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setHighlightIndex(\n (highlightIndex - 1 + Math.max(len, 1)) % Math.max(len, 1),\n );\n return true;\n }\n if (e.key === \"Enter\") {\n e.preventDefault();\n const item = filteredOptions[highlightIndex];\n if (item) selectOption(item, textarea);\n return true;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n closeSuggestions();\n return true;\n }\n return false;\n },\n [\n activeTrigger,\n filteredOptions,\n highlightIndex,\n searchState,\n selectOption,\n closeSuggestions,\n loadMore,\n ],\n );\n\n return {\n visible,\n setVisible,\n mentions,\n activeTrigger,\n filteredOptions,\n highlightIndex,\n setHighlightIndex,\n searchLoading: searchState.loading,\n searchHasMore: searchState.hasMore,\n handleTextChange,\n handleKeyDown,\n selectOption,\n closeSuggestions,\n loadMore,\n rawToVisible,\n visibleToRaw,\n caretPosRef,\n getItemForMention,\n };\n}\n\nfunction getItemKey(trigger: MentionTrigger<any>, item: unknown): string {\n const serialized = trigger.serialize(item);\n const re = new RegExp(\n trigger.pattern.source,\n trigger.pattern.flags.replace(\"g\", \"\"),\n );\n const m = re.exec(serialized);\n if (m) {\n return trigger.parseMatch(m).key;\n }\n return serialized;\n}\n",
|
|
10
10
|
"export function escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n"
|
|
11
11
|
],
|
|
12
|
-
"mappings": "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",
|
|
13
|
-
"debugId": "
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "0811411863941EFA64756E2164756E21",
|
|
14
14
|
"names": []
|
|
15
15
|
}
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type React from "react";
|
|
2
|
+
export interface MentionItemData {
|
|
3
|
+
key: string;
|
|
4
|
+
displayText: string;
|
|
5
|
+
trigger: string;
|
|
6
|
+
item: unknown;
|
|
7
|
+
}
|
|
2
8
|
export interface MentionTrigger<T = unknown> {
|
|
3
9
|
/** The character(s) that activate this trigger (e.g., "@", "#") */
|
|
4
10
|
trigger: string;
|
|
@@ -22,10 +28,14 @@ export interface MentionTrigger<T = unknown> {
|
|
|
22
28
|
}>;
|
|
23
29
|
/** Custom option rendering */
|
|
24
30
|
renderOption?: (item: T, highlighted: boolean) => React.ReactNode;
|
|
31
|
+
/** CSS class for dropdown options, or a function for conditional styling per item */
|
|
32
|
+
optionClassName?: string | ((item: T) => string);
|
|
25
33
|
/** Custom mention highlight rendering */
|
|
26
|
-
renderMention?: (displayText: string) => React.ReactNode;
|
|
27
|
-
/** CSS class for highlighted mentions in the overlay */
|
|
28
|
-
mentionClassName?: string;
|
|
34
|
+
renderMention?: (displayText: string, item?: unknown) => React.ReactNode;
|
|
35
|
+
/** CSS class for highlighted mentions in the overlay, or a function for conditional styling */
|
|
36
|
+
mentionClassName?: string | ((mention: MentionItemData) => string);
|
|
37
|
+
/** Action trigger: called instead of inserting a mention. Return string to insert as plain text, or null to cancel. */
|
|
38
|
+
onSelect?: (item: T) => Promise<string | null> | string | null;
|
|
29
39
|
}
|
|
30
40
|
export interface MentionInputProps {
|
|
31
41
|
triggers: MentionTrigger<any>[];
|
|
@@ -48,6 +58,8 @@ export interface MentionInputProps {
|
|
|
48
58
|
dropdownClassName?: string;
|
|
49
59
|
/** Dropdown width in pixels */
|
|
50
60
|
dropdownWidth?: number;
|
|
61
|
+
/** Text shown while loading async results (default: "Loading...") */
|
|
62
|
+
loadingText?: string;
|
|
51
63
|
/** Full custom dropdown rendering */
|
|
52
64
|
renderDropdown?: (props: DropdownRenderProps) => React.ReactNode;
|
|
53
65
|
"aria-label"?: string;
|
|
@@ -29,5 +29,6 @@ export declare function useMentionEngine(options: MentionEngineOptions): {
|
|
|
29
29
|
rawToVisible: (raw: string) => string;
|
|
30
30
|
visibleToRaw: (vis: string, mentionsList: ActiveMention[]) => string;
|
|
31
31
|
caretPosRef: import("react").RefObject<number | null>;
|
|
32
|
+
getItemForMention: (triggerChar: string, key: string) => unknown;
|
|
32
33
|
};
|
|
33
34
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mentionize",
|
|
3
3
|
"author": "canta2899",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.2",
|
|
5
5
|
"description": "A dependency-free React mention input with support for multiple triggers, async search, and full customization",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/cjs/index.js",
|