UNPKG

@replyke/core

Version:

Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.

136 lines 5.26 kB
"use strict"; 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