@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
136 lines • 5.26 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const useFetchManySpaces_1 = __importDefault(require("./useFetchManySpaces"));
const handleError_1 = require("../../utils/handleError");
function escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
const useSpaceMentions = ({ content, setContent, focus, cursorPosition, isSelectionActive, trigger = "#", minChars = 3, debounceDelay = 1000, validPattern = "[\\w.\\-]+", }) => {
const fetchManySpaces = (0, useFetchManySpaces_1.default)();
const [loadingState, setLoadingState] = (0, react_1.useState)(false);
const [mentions, setMentions] = (0, react_1.useState)([]);
const [isSpaceMentionActive, setIsSpaceMentionActive] = (0, react_1.useState)(false);
const [mentionTrigger, setMentionTrigger] = (0, react_1.useState)("");
const [spaceMentionSuggestions, setSpaceMentionSuggestions] = (0, react_1.useState)([]);
const debounceTimerRef = (0, react_1.useRef)(null);
const resetSpaceMentions = () => {
setMentions([]);
setIsSpaceMentionActive(false);
setMentionTrigger("");
setSpaceMentionSuggestions([]);
setLoadingState(false);
};
const addSpaceMention = (space) => {
if (!space.slug)
throw new Error("Space has no slug set");
setMentions((prevMentions) => {
if (prevMentions.some((mention) => mention.id === space.id)) {
return prevMentions;
}
return [
...prevMentions,
{
id: space.id,
slug: space.slug,
type: "space",
},
];
});
};
const handleSpaceMentionClick = (space) => {
const mentionRegex = new RegExp(`${escapeRegex(trigger)}${escapeRegex(mentionTrigger)}(\\s|$)`);
setContent(content.replace(mentionRegex, `${trigger}${space.slug} `));
addSpaceMention(space);
setIsSpaceMentionActive(false);
setMentionTrigger("");
setSpaceMentionSuggestions([]);
setLoadingState(false);
focus();
};
const handleFetchSpaceSuggestions = (0, react_1.useCallback)(async (query) => {
try {
const result = await fetchManySpaces({
searchAny: query,
limit: 5,
});
if (result.data && result.data.length > 0) {
setSpaceMentionSuggestions(result.data);
}
else {
setSpaceMentionSuggestions([]);
setIsSpaceMentionActive(false);
}
}
catch (err) {
(0, handleError_1.handleError)(err, "Error fetching space suggestions");
}
finally {
setLoadingState(false);
}
}, [fetchManySpaces]);
(0, react_1.useEffect)(() => {
let start = cursorPosition - 1;
// Move backward from cursor to find the word directly before the cursor
while (start >= 0 && content[start] !== " ") {
start--;
}
// Extract potential trigger word (start + 1 because `start` is on the space)
const potentialTrigger = content.slice(start + 1, cursorPosition);
const validMentionPattern = new RegExp("^" + escapeRegex(trigger) + validPattern + "$");
if (!isSelectionActive &&
validMentionPattern.test(potentialTrigger) &&
potentialTrigger.length >= trigger.length + minChars) {
const triggerText = potentialTrigger.slice(trigger.length);
setMentionTrigger(triggerText);
setIsSpaceMentionActive(true);
setLoadingState(true);
// Clear the previous debounce timer
if (debounceTimerRef.current) {
clearTimeout(debounceTimerRef.current);
}
// Set a new debounce timer
debounceTimerRef.current = setTimeout(() => {
handleFetchSpaceSuggestions(triggerText);
}, debounceDelay);
}
else {
if (debounceTimerRef.current) {
clearTimeout(debounceTimerRef.current);
}
setMentionTrigger("");
setIsSpaceMentionActive(false);
setSpaceMentionSuggestions([]);
setLoadingState(false);
}
// Cleanup on component unmount to clear any remaining timer
return () => {
if (debounceTimerRef.current) {
clearTimeout(debounceTimerRef.current);
}
};
}, [
cursorPosition,
isSelectionActive,
handleFetchSpaceSuggestions,
content,
trigger,
minChars,
debounceDelay,
validPattern,
]);
return {
isSpaceMentionActive,
loading: loadingState,
spaceMentionSuggestions,
handleSpaceMentionClick,
mentions,
addSpaceMention,
resetSpaceMentions,
};
};
exports.default = useSpaceMentions;
//# sourceMappingURL=useSpaceMentions.js.map