UNPKG

@searchwithaura/react-mention-textarea

Version:

A powerful React component for @ mentions with multi-layer navigation, search functionality, and custom action cards

1 lines 69.3 kB
{"version":3,"file":"index.es","sources":["../node_modules/react/cjs/react-jsx-runtime.production.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../src/utils.ts","../src/hooks/useKeyboardNavigation.ts","../src/ContextMenu.tsx","../src/ActionCards/NotionPageCard.tsx","../src/hooks/useMentionDetection.ts","../src/MentionTextarea.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return (type.displayName || \"Context\") + \".Provider\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(\n type,\n key,\n self,\n source,\n owner,\n props,\n debugStack,\n debugTask\n ) {\n self = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== self ? self : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n source,\n self,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n self,\n source,\n getOwner(),\n maybeKey,\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_ELEMENT_TYPE &&\n node._store &&\n (node._store.validated = 1);\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\");\n Symbol.for(\"react.provider\");\n var REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n \"react-stack-bottom-frame\": function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React[\"react-stack-bottom-frame\"].bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey, source, self) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n source,\n self,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import { MentionItem } from './types';\n\nexport const getCaretCoordinates = (element: HTMLTextAreaElement, position: number) => {\n const div = document.createElement('div');\n const style = getComputedStyle(element);\n\n // Copy styles from textarea to div\n const properties = [\n 'boxSizing', 'width', 'height', 'overflowX', 'overflowY',\n 'borderTopWidth', 'borderRightWidth', 'borderBottomWidth', 'borderLeftWidth',\n 'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',\n 'fontStyle', 'fontVariant', 'fontWeight', 'fontStretch', 'fontSize',\n 'fontSizeAdjust', 'lineHeight', 'fontFamily', 'textAlign',\n 'textTransform', 'textIndent', 'textDecoration', 'letterSpacing', 'wordSpacing'\n ];\n\n properties.forEach(prop => {\n div.style[prop as any] = style[prop as any];\n });\n\n div.style.position = 'absolute';\n div.style.top = '-9999px';\n div.style.left = '-9999px';\n div.style.whiteSpace = 'pre-wrap';\n div.style.wordWrap = 'break-word';\n\n const textContent = element.value.substring(0, position);\n div.textContent = textContent;\n\n const span = document.createElement('span');\n span.textContent = element.value.substring(position) || '.';\n div.appendChild(span);\n\n document.body.appendChild(div);\n\n const coordinates = {\n top: span.offsetTop + parseInt(style.borderTopWidth),\n left: span.offsetLeft + parseInt(style.borderLeftWidth),\n height: parseInt(style.lineHeight)\n };\n\n document.body.removeChild(div);\n return coordinates;\n};\n\nexport const findMentionTrigger = (text: string, cursorPosition: number, triggers: string[]) => {\n const textBeforeCursor = text.substring(0, cursorPosition);\n\n for (const trigger of triggers) {\n const lastTriggerIndex = textBeforeCursor.lastIndexOf(trigger);\n\n if (lastTriggerIndex !== -1) {\n const textAfterTrigger = textBeforeCursor.substring(lastTriggerIndex + 1);\n\n // Check if there's no whitespace after the trigger (still typing the mention)\n if (!textAfterTrigger.includes(' ') && !textAfterTrigger.includes('\\n')) {\n return {\n trigger,\n position: lastTriggerIndex,\n query: textAfterTrigger\n };\n }\n }\n }\n\n return null;\n};\n\nexport const filterItems = (items: MentionItem[], query: string, maxResults = 10): MentionItem[] => {\n if (!query.trim()) {\n return items.slice(0, maxResults);\n }\n\n const lowerQuery = query.toLowerCase();\n\n const filtered = items.filter(item =>\n item.label.toLowerCase().includes(lowerQuery) ||\n item.description?.toLowerCase().includes(lowerQuery)\n );\n\n // Sort by relevance (exact matches first, then starts with, then contains)\n filtered.sort((a, b) => {\n const aLabel = a.label.toLowerCase();\n const bLabel = b.label.toLowerCase();\n\n if (aLabel === lowerQuery) return -1;\n if (bLabel === lowerQuery) return 1;\n\n if (aLabel.startsWith(lowerQuery) && !bLabel.startsWith(lowerQuery)) return -1;\n if (bLabel.startsWith(lowerQuery) && !aLabel.startsWith(lowerQuery)) return 1;\n\n return 0;\n });\n\n return filtered.slice(0, maxResults);\n};\n\nexport const insertMention = (\n text: string,\n mentionText: string,\n triggerPosition: number,\n currentPosition: number\n): { newText: string; newCursorPosition: number } => {\n const beforeTrigger = text.substring(0, triggerPosition);\n const afterCursor = text.substring(currentPosition);\n\n const newText = beforeTrigger + mentionText + ' ' + afterCursor;\n const newCursorPosition = triggerPosition + mentionText.length + 1;\n\n return { newText, newCursorPosition };\n};\n\nexport const debounce = <T extends (...args: any[]) => any>(\n func: T,\n wait: number\n): ((...args: Parameters<T>) => void) => {\n let timeout: NodeJS.Timeout;\n\n return (...args: Parameters<T>) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => func(...args), wait);\n };\n};\n\nexport const formatMentionWithSource = (\n item: MentionItem,\n sourcePath: string[],\n sourceIds: string[],\n options: {\n showSource?: boolean;\n sourceFormat?: 'label' | 'id';\n sourceSeparator?: string;\n pathSeparator?: string;\n } = {}\n): string => {\n const {\n showSource = true,\n sourceFormat = 'label',\n sourceSeparator = ':',\n pathSeparator = ':'\n } = options;\n\n if (!showSource || sourcePath.length === 0) {\n return item.label;\n }\n\n const pathToUse = sourceFormat === 'id' ? sourceIds : sourcePath;\n const sourcePrefix = pathToUse.join(pathSeparator);\n\n return `${sourcePrefix}${sourceSeparator}${item.label}`;\n};\n\nexport const createMentionSelectData = (\n item: MentionItem,\n sourcePath: string[],\n sourceIds: string[],\n trigger: string,\n displayText: string\n) => {\n return {\n displayText,\n sourcePath: [...sourcePath],\n sourceIds: [...sourceIds],\n item,\n trigger,\n fullPath: [...sourcePath],\n fullIds: [...sourceIds]\n };\n};\n\nexport const getThemeClasses = (theme: 'light' | 'dark' | 'auto' = 'auto') => {\n const baseClasses = {\n menu: 'border rounded-lg shadow-lg backdrop-blur-sm',\n menuLight: 'bg-white border-gray-200 text-gray-900',\n menuDark: 'bg-gray-800 border-gray-700 text-gray-100',\n item: 'px-3 py-2 cursor-pointer transition-colors duration-150',\n itemHover: 'hover:bg-gray-100 dark:hover:bg-gray-700',\n itemSelected: 'bg-blue-100 dark:bg-blue-900',\n search: 'w-full px-3 py-2 border-b outline-none',\n searchLight: 'border-gray-200 bg-white text-gray-900 placeholder-gray-500',\n searchDark: 'border-gray-700 bg-gray-800 text-gray-100 placeholder-gray-400'\n };\n\n if (theme === 'light') {\n return {\n menu: `${baseClasses.menu} ${baseClasses.menuLight}`,\n item: baseClasses.item,\n itemHover: 'hover:bg-gray-100',\n itemSelected: 'bg-blue-100',\n search: `${baseClasses.search} ${baseClasses.searchLight}`\n };\n }\n\n if (theme === 'dark') {\n return {\n menu: `${baseClasses.menu} ${baseClasses.menuDark}`,\n item: baseClasses.item,\n itemHover: 'hover:bg-gray-700',\n itemSelected: 'bg-blue-900',\n search: `${baseClasses.search} ${baseClasses.searchDark}`\n };\n }\n\n // Auto theme\n return {\n menu: `${baseClasses.menu} bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700 text-gray-900 dark:text-gray-100`,\n item: baseClasses.item,\n itemHover: 'hover:bg-gray-100 dark:hover:bg-gray-700',\n itemSelected: 'bg-blue-100 dark:bg-blue-900',\n search: `${baseClasses.search} border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400`\n };\n};\n","import { useCallback, useEffect } from 'react';\nimport { MentionItem } from '../types';\n\ninterface UseKeyboardNavigationProps {\n isMenuOpen: boolean;\n items: MentionItem[];\n selectedIndex: number;\n onSelect: (item: MentionItem) => void;\n onClose: () => void;\n onNavigateBack?: () => void;\n canNavigateBack?: boolean;\n setSelectedIndex: (index: number) => void;\n}\n\nexport const useKeyboardNavigation = ({\n isMenuOpen,\n items,\n selectedIndex,\n onSelect,\n onClose,\n onNavigateBack,\n canNavigateBack,\n setSelectedIndex\n}: UseKeyboardNavigationProps) => {\n const handleKeyDown = useCallback((event: KeyboardEvent) => {\n if (!isMenuOpen) return;\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setSelectedIndex(selectedIndex < items.length - 1 ? selectedIndex + 1 : 0);\n break;\n\n case 'ArrowUp':\n event.preventDefault();\n setSelectedIndex(selectedIndex > 0 ? selectedIndex - 1 : items.length - 1);\n break;\n\n case 'Enter':\n event.preventDefault();\n if (items[selectedIndex]) {\n onSelect(items[selectedIndex]);\n }\n break;\n\n case 'Escape':\n event.preventDefault();\n onClose();\n break;\n\n case 'ArrowLeft':\n if (canNavigateBack && onNavigateBack) {\n event.preventDefault();\n onNavigateBack();\n }\n break;\n\n case 'Tab':\n event.preventDefault();\n onClose();\n break;\n\n default:\n break;\n }\n }, [\n isMenuOpen,\n items,\n selectedIndex,\n onSelect,\n onClose,\n onNavigateBack,\n canNavigateBack,\n setSelectedIndex\n ]);\n\n useEffect(() => {\n if (isMenuOpen) {\n document.addEventListener('keydown', handleKeyDown);\n return () => {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }\n }, [isMenuOpen, handleKeyDown]);\n\n return { handleKeyDown };\n};\n","import React, { useRef, useEffect, useState } from 'react';\nimport { ContextMenuProps, MentionItem } from './types';\nimport { filterItems, getThemeClasses } from './utils';\nimport { useKeyboardNavigation } from './hooks/useKeyboardNavigation';\n\nexport const ContextMenu: React.FC<ContextMenuProps> = ({\n isOpen,\n position,\n items,\n selectedIndex,\n searchQuery,\n onSelect,\n onClose,\n onSearch,\n onNavigateBack,\n canNavigateBack = false,\n maxHeight = 300,\n theme = 'auto'\n}) => {\n const menuRef = useRef<HTMLDivElement>(null);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const [localSearchQuery, setLocalSearchQuery] = useState(searchQuery);\n\n const filteredItems = filterItems(items, localSearchQuery);\n const themeClasses = getThemeClasses(theme);\n\n useKeyboardNavigation({\n isMenuOpen: isOpen,\n items: filteredItems,\n selectedIndex,\n onSelect,\n onClose,\n onNavigateBack,\n canNavigateBack,\n setSelectedIndex: (index) => {\n // This will be handled by the parent component\n }\n });\n\n useEffect(() => {\n setLocalSearchQuery(searchQuery);\n }, [searchQuery]);\n\n useEffect(() => {\n if (isOpen && searchInputRef.current) {\n searchInputRef.current.focus();\n }\n }, [isOpen]);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n onClose();\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }\n }, [isOpen, onClose]);\n\n const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setLocalSearchQuery(value);\n onSearch(value);\n };\n\n const handleItemClick = (item: MentionItem) => {\n onSelect(item);\n };\n\n const renderItem = (item: MentionItem, index: number) => {\n const isSelected = index === selectedIndex;\n const itemClasses = `${themeClasses.item} ${\n isSelected ? themeClasses.itemSelected : themeClasses.itemHover\n }`;\n\n return (\n <div\n key={item.id}\n className={itemClasses}\n onClick={() => handleItemClick(item)}\n onMouseEnter={() => {\n // Update selected index on hover\n }}\n >\n <div className=\"flex items-center gap-3\">\n {item.icon && (\n <span className=\"text-lg flex-shrink-0\">{item.icon}</span>\n )}\n {item.avatar && (\n <img\n src={item.avatar}\n alt={item.label}\n className=\"w-6 h-6 rounded-full flex-shrink-0\"\n />\n )}\n <div className=\"flex-1 min-w-0\">\n <div className=\"font-medium truncate\">{item.label}</div>\n {item.description && (\n <div className=\"text-sm text-gray-500 dark:text-gray-400 truncate\">\n {item.description}\n </div>\n )}\n </div>\n {item.children && (\n <span className=\"text-gray-400 dark:text-gray-500 flex-shrink-0\">\n →\n </span>\n )}\n </div>\n </div>\n );\n };\n\n if (!isOpen) return null;\n\n return (\n <div\n ref={menuRef}\n className={`fixed z-50 min-w-64 max-w-80 ${themeClasses.menu}`}\n style={{\n left: position.x,\n top: position.y,\n maxHeight: `${maxHeight}px`\n }}\n >\n {/* Header with search and back button */}\n <div className=\"flex items-center\">\n {canNavigateBack && (\n <button\n onClick={onNavigateBack}\n className=\"p-2 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\n title=\"Go back\"\n >\n <span className=\"text-gray-500 dark:text-gray-400\">←</span>\n </button>\n )}\n <input\n ref={searchInputRef}\n type=\"text\"\n value={localSearchQuery}\n onChange={handleSearchChange}\n placeholder=\"Search...\"\n className={`${themeClasses.search} ${canNavigateBack ? 'pl-2' : ''}`}\n />\n </div>\n\n {/* Items list */}\n <div className=\"max-h-64 overflow-y-auto\">\n {filteredItems.length > 0 ? (\n filteredItems.map((item, index) => renderItem(item, index))\n ) : (\n <div className=\"px-3 py-4 text-center text-gray-500 dark:text-gray-400\">\n No items found\n </div>\n )}\n </div>\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { ActionCardProps } from '../types';\n\nexport const NotionPageCard: React.FC<ActionCardProps> = ({\n item,\n onSubmit,\n onCancel\n}) => {\n const [formData, setFormData] = useState({\n title: '',\n content: '',\n tags: '',\n database: 'default'\n });\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!formData.title.trim()) return;\n\n const result = `[Notion Page: ${formData.title}${formData.tags ? ` #${formData.tags.replace(/,\\s*/g, ' #')}` : ''}]`;\n onSubmit(result);\n };\n\n const handleInputChange = (field: string, value: string) => {\n setFormData(prev => ({ ...prev, [field]: value }));\n };\n\n return (\n <div className=\"p-4 min-w-80\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"font-semibold text-lg\">Create Notion Page</h3>\n <button\n onClick={onCancel}\n className=\"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n ✕\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n Page Title *\n </label>\n <input\n type=\"text\"\n value={formData.title}\n onChange={(e) => handleInputChange('title', e.target.value)}\n placeholder=\"Enter page title...\"\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n autoFocus\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n Database\n </label>\n <select\n value={formData.database}\n onChange={(e) => handleInputChange('database', e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"default\">Default Database</option>\n <option value=\"projects\">Projects</option>\n <option value=\"notes\">Notes</option>\n <option value=\"tasks\">Tasks</option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n Initial Content\n </label>\n <textarea\n value={formData.content}\n onChange={(e) => handleInputChange('content', e.target.value)}\n placeholder=\"Optional initial content...\"\n rows={3}\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n Tags\n </label>\n <input\n type=\"text\"\n value={formData.tags}\n onChange={(e) => handleInputChange('tags', e.target.value)}\n placeholder=\"tag1, tag2, tag3...\"\n className=\"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n <p className=\"text-xs text-gray-500 dark:text-gray-400 mt-1\">\n Separate tags with commas\n </p>\n </div>\n\n <div className=\"flex gap-2 pt-2\">\n <button\n type=\"submit\"\n disabled={!formData.title.trim()}\n className=\"flex-1 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white px-4 py-2 rounded-md font-medium transition-colors\"\n >\n Create Page\n </button>\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n </div>\n );\n};\n","import { useState, useCallback, useRef } from 'react';\nimport { MentionConfig, MenuState } from '../types';\nimport { findMentionTrigger, getCaretCoordinates } from '../utils';\n\nexport const useMentionDetection = (\n textareaRef: React.RefObject<HTMLTextAreaElement | null>,\n mentions: MentionConfig[]\n) => {\n const [menuState, setMenuState] = useState<MenuState>({\n isOpen: false,\n position: { x: 0, y: 0 },\n currentLayer: 0,\n layerStack: [],\n searchQuery: '',\n selectedIndex: 0,\n triggerChar: '',\n triggerPosition: 0,\n sourcePath: [],\n sourceIds: []\n });\n\n const triggers = mentions.map(m => m.trigger);\n\n const detectMention = useCallback((text: string, cursorPosition: number) => {\n if (!textareaRef.current) return;\n\n const mentionTrigger = findMentionTrigger(text, cursorPosition, triggers);\n\n if (mentionTrigger) {\n const mentionConfig = mentions.find(m => m.trigger === mentionTrigger.trigger);\n if (!mentionConfig) return;\n\n const coordinates = getCaretCoordinates(textareaRef.current, mentionTrigger.position);\n const rect = textareaRef.current.getBoundingClientRect();\n\n setMenuState(prev => ({\n ...prev,\n isOpen: true,\n position: {\n x: rect.left + coordinates.left,\n y: rect.top + coordinates.top + coordinates.height + 4\n },\n currentLayer: 0,\n layerStack: [mentionConfig.data],\n searchQuery: mentionTrigger.query,\n selectedIndex: 0,\n triggerChar: mentionTrigger.trigger,\n triggerPosition: mentionTrigger.position,\n sourcePath: [],\n sourceIds: []\n }));\n } else {\n setMenuState(prev => ({ ...prev, isOpen: false }));\n }\n }, [textareaRef, mentions, triggers]);\n\n const closeMenu = useCallback(() => {\n setMenuState(prev => ({\n ...prev,\n isOpen: false,\n sourcePath: [],\n sourceIds: [],\n currentLayer: 0,\n layerStack: []\n }));\n }, []);\n\n const updateSearch = useCallback((query: string) => {\n setMenuState(prev => ({ ...prev, searchQuery: query, selectedIndex: 0 }));\n }, []);\n\n const navigateToLayer = useCallback((items: any[], sourceItem?: any) => {\n setMenuState(prev => ({\n ...prev,\n currentLayer: prev.currentLayer + 1,\n layerStack: [...prev.layerStack, items],\n searchQuery: '',\n selectedIndex: 0,\n sourcePath: sourceItem ? [...prev.sourcePath, sourceItem.label] : prev.sourcePath,\n sourceIds: sourceItem ? [...prev.sourceIds, sourceItem.id] : prev.sourceIds\n }));\n }, []);\n\n const navigateBack = useCallback(() => {\n setMenuState(prev => {\n if (prev.currentLayer > 0) {\n const newLayerStack = prev.layerStack.slice(0, -1);\n const newSourcePath = prev.sourcePath.slice(0, -1);\n const newSourceIds = prev.sourceIds.slice(0, -1);\n return {\n ...prev,\n currentLayer: prev.currentLayer - 1,\n layerStack: newLayerStack,\n searchQuery: '',\n selectedIndex: 0,\n sourcePath: newSourcePath,\n sourceIds: newSourceIds\n };\n }\n return prev;\n });\n }, []);\n\n const setSelectedIndex = useCallback((index: number) => {\n setMenuState(prev => ({ ...prev, selectedIndex: index }));\n }, []);\n\n return {\n menuState,\n detectMention,\n closeMenu,\n updateSearch,\n navigateToLayer,\n navigateBack,\n setSelectedIndex\n };\n};\n","import React, { useRef, useCallback, useState } from 'react';\nimport { MentionTextareaProps, MentionItem } from './types';\nimport { ContextMenu } from './ContextMenu';\nimport { NotionPageCard } from './ActionCards/NotionPageCard';\nimport { useMentionDetection } from './hooks/useMentionDetection';\nimport { useKeyboardNavigation } from './hooks/useKeyboardNavigation';\nimport { insertMention, filterItems, formatMentionWithSource, createMentionSelectData } from './utils';\n\nexport const MentionTextarea: React.FC<MentionTextareaProps> = ({\n value,\n onChange,\n mentions,\n placeholder = 'Type @ to mention...',\n className = '',\n onMentionSelect,\n theme = 'auto',\n maxMenuHeight = 300,\n disabled = false,\n rows = 4,\n autoFocus = false,\n showSource = true,\n sourceFormat = 'label',\n sourceSeparator = ':',\n pathSeparator = ':'\n}) => {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [showActionCard, setShowActionCard] = useState<MentionItem | null>(null);\n const [cursorPosition, setCursorPosition] = useState(0);\n\n const {\n menuState,\n detectMention,\n closeMenu,\n updateSearch,\n navigateToLayer,\n navigateBack,\n setSelectedIndex\n } = useMentionDetection(textareaRef, mentions);\n\n const currentItems = menuState.layerStack[menuState.currentLayer] || [];\n const filteredItems = filterItems(currentItems, menuState.searchQuery);\n\n const handleTextChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const newValue = e.target.value;\n const newCursorPosition = e.target.selectionStart;\n\n onChange(newValue);\n setCursorPosition(newCursorPosition);\n detectMention(newValue, newCursorPosition);\n }, [onChange, detectMention]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n setCursorPosition(e.currentTarget.selectionStart);\n }, []);\n\n const handleSelect = useCallback((item: MentionItem) => {\n if (item.children && item.children.length > 0) {\n // Navigate to sub-menu and track source path\n navigateToLayer(item.children, item);\n return;\n }\n\n if (item.component === 'NotionPageCard') {\n // Show action card\n setShowActionCard(item);\n return;\n }\n\n // Handle regular mention selection with source information\n const displayText = formatMentionWithSource(\n item,\n menuState.sourcePath,\n menuState.sourceIds,\n {\n showSource,\n sourceFormat,\n sourceSeparator,\n pathSeparator\n }\n );\n\n const { newText, newCursorPosition } = insertMention(\n value,\n displayText,\n menuState.triggerPosition,\n cursorPosition\n );\n\n onChange(newText);\n closeMenu();\n\n // Set cursor position after insertion\n setTimeout(() => {\n if (textareaRef.current) {\n textareaRef.current.setSelectionRange(newCursorPosition, newCursorPosition);\n textareaRef.current.focus();\n }\n }, 0);\n\n // Call the enhanced callback with structured data\n if (onMentionSelect) {\n const mentionData = createMentionSelectData(\n item,\n menuState.sourcePath,\n menuState.sourceIds,\n menuState.triggerChar,\n displayText\n );\n onMentionSelect(mentionData);\n }\n }, [\n value,\n cursorPosition,\n menuState.triggerPosition,\n menuState.sourcePath,\n menuState.sourceIds,\n menuState.triggerChar,\n onChange,\n closeMenu,\n onMentionSelect,\n navigateToLayer,\n showSource,\n sourceFormat,\n sourceSeparator,\n pathSeparator\n ]);\n\n const handleActionCardSubmit = useCallback((result: string) => {\n const { newText, newCursorPosition } = insertMention(\n value,\n result,\n menuState.triggerPosition,\n cursorPosition\n );\n\n onChange(newText);\n setShowActionCard(null);\n closeMenu();\n\n // Set cursor position after insertion\n setTimeout(() => {\n if (textareaRef.current) {\n textareaRef.current.setSelectionRange(newCursorPosition, newCursorPosition);\n textareaRef.current.focus();\n }\n }, 0);\n }, [value, cursorPosition, menuState.triggerPosition, onChange, closeMenu]);\n\n const handleActionCardCancel = useCallback(() => {\n setShowActionCard(null);\n closeMenu();\n\n // Return focus to textarea\n setTimeout(() => {\n if (textareaRef.current) {\n textareaRef.current.focus();\n }\n }, 0);\n }, [closeMenu]);\n\n useKeyboardNavigation({\n isMenuOpen: menuState.isOpen && !showActionCard,\n items: filteredItems,\n selectedIndex: menuState.selectedIndex,\n onSelect: handleSelect,\n onClose: closeMenu,\n onNavigateBack: menuState.currentLayer > 0 ? navigateBack : undefined,\n canNavigateBack: menuState.currentLayer > 0,\n setSelectedIndex\n });\n\n const baseTextareaClasses = `\n w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md\n bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100\n placeholder-gray-500 dark:placeholder-gray-400\n focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent\n resize-none transition-colors\n ${disabled ? 'opacity-50 cursor-not-allowed' : ''}\n `.trim();\n\n return (\n <div className=\"relative\">\n <textarea\n ref={textareaRef}\n value={value}\n onChange={handleTextChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n className={`${baseTextareaClasses} ${className}`}\n disabled={disabled}\n rows={rows}\n autoFocus={autoFocus}\n />\n\n {/* Context Menu */}\n <ContextMenu\n isOpen={menuState.isOpen && !showActionCard}\n position={menuState.position}\n items={filteredItems}\n selectedIndex={menuState.selectedIndex}\n searchQuery={menuState.searchQuery}\n onSelect={handleSelect}\n onClose={closeMenu}\n onSearch={updateSearch}\n onNavigateBack={menuState.currentLayer > 0 ? navigateBack : undefined}\n canNavigateBack={menuState.currentLayer > 0}\n maxHeight={maxMenuHeight}\n theme={theme}\n />\n\n {/* Action Card */}\n {showActionCard && (\n <div\n className=\"fixed z-50 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg\"\n style={{\n left: menuState.position.x,\n top: menuState.position.y\n }}\n >\n {showActionCard.component === 'NotionPageCard' && (\n <NotionPageCard\n item={showActionCard}\n onSubmit={handleActionCardSubmit}\n onCancel={handleActionCardCancel}\n />\n )}\n </div>\n )}\n </div>\n );\n};\n"],"names":["REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","reactJsxRuntime_production","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","self","source","owner","debugStack","debugTask","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","k","didWarnAboutKeySpread","node","React","require$$0","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","getCaretCoordinates","element","position","div","style","prop","textContent","span","coordinates","findMentionTrigger","text","cursorPosition","triggers","textBeforeCursor","trigger","lastTriggerIndex","textAfterTrigger","filterItems","items","query","maxResults","lowerQuery","filtered","item","a","b","aLabel","bLabel","insertMention","mentionText","triggerPosition","currentPosition","beforeTrigger","afterCursor","newText","newCursorPosition","debounce","func","wait","timeout","args","formatMentionWithSource","sourcePath","sourceIds","options","showSource","sourceFormat","sourceSeparator","pathSeparator","createMentionSelectData","displayText","getThemeClasses","theme","baseClasses","useKeyboardNavigation","isMenuOpen","selectedIndex","onSelect","onClose","onNavigateBack","canNavigateBack","setSelectedIndex","handleKeyDown","useCallback","event","useEffect","ContextMenu","isOpen","searchQuery","onSearch","maxHeight","menuRef","useRef","searchInputRef","localSearchQuery","setLocalSearchQuery","useState","filteredItems","themeClasses","index","handleClickOutside","handleSearchChange","e","handleItemClick","renderItem","isSelected","itemClasses","jsx","jsxs","NotionPageCard","onSubmit","onCancel","formData","setFormData","handleSubmit","result","handleInputChange","field","prev","useMentionDetection","textareaRef","mentions","menuState","setMenuState","m","detectMention","mentionTrigger","mentionConfig","rect","closeMenu","updateSearch","navigateToLayer","sourceItem","navigateBack","newLayerStack","newSourcePath","newSourceIds","MentionTextarea","onChange","placeholder","className","onMentionSelect","maxMenuHeight","disabled","rows","autoFocus","showActionCard","setShowActionCard","setCursorPosition","currentItems","handleTextChange","newValue","handleSelect","mentionData","handleActionCardSubmit","handleActionCardCancel","baseTextareaClasses"],"mappings":"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