@chayns-components/emoji-input 5.6.4 → 5.6.8

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.
Files changed (41) hide show
  1. package/lib/cjs/build.test.js +34 -0
  2. package/lib/cjs/build.test.js.map +1 -0
  3. package/lib/cjs/components/emoji-input/EmojiInput.js +8 -1
  4. package/lib/cjs/components/emoji-input/EmojiInput.js.map +1 -1
  5. package/lib/cjs/components/emoji-input/EmojiInput.test.js +120 -0
  6. package/lib/cjs/components/emoji-input/EmojiInput.test.js.map +1 -0
  7. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js +48 -219
  8. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js.map +1 -1
  9. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js +316 -0
  10. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js.map +1 -0
  11. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js +1 -0
  12. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js.map +1 -1
  13. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js +109 -0
  14. package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js.map +1 -0
  15. package/lib/cjs/utils/selection.js +61 -31
  16. package/lib/cjs/utils/selection.js.map +1 -1
  17. package/lib/cjs/utils/selection.test.js +160 -0
  18. package/lib/cjs/utils/selection.test.js.map +1 -0
  19. package/lib/esm/build.test.js +32 -0
  20. package/lib/esm/build.test.js.map +1 -0
  21. package/lib/esm/components/emoji-input/EmojiInput.js +4 -1
  22. package/lib/esm/components/emoji-input/EmojiInput.js.map +1 -1
  23. package/lib/esm/components/emoji-input/EmojiInput.test.js +116 -0
  24. package/lib/esm/components/emoji-input/EmojiInput.test.js.map +1 -0
  25. package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js +47 -218
  26. package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js.map +1 -1
  27. package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js +312 -0
  28. package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js.map +1 -0
  29. package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js +1 -0
  30. package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js.map +1 -1
  31. package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js +101 -0
  32. package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js.map +1 -0
  33. package/lib/esm/utils/selection.js +59 -30
  34. package/lib/esm/utils/selection.js.map +1 -1
  35. package/lib/esm/utils/selection.test.js +158 -0
  36. package/lib/esm/utils/selection.test.js.map +1 -0
  37. package/lib/types/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.d.ts +15 -0
  38. package/lib/types/utils/selection.d.ts +1 -1
  39. package/package.json +3 -3
  40. package/lib/types/utils/emoji.test.d.ts +0 -1
  41. package/lib/types/utils/text.test.d.ts +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmojiPickerEmojis.test.js","names":["fireEvent","render","screen","waitFor","React","ThemeProvider","beforeEach","describe","expect","it","vi","EmojiPickerEmojis","fixtures","hoisted","emojis","emoji","name","skin_tone_support","addHistory","fn","history","mock","default","slug","slice","Object","fromEntries","map","data","useEmojiHistory","addOrUpdateEmojiInHistory","historyEmojis","useRef","useIsMeasuredClone","setup","onSelect","renderPicker","searchString","selectedCategory","createElement","theme","view","container","querySelectorAll","toHaveLength","update","search","category","rerender","key","ctrlKey","keyDown","document","navigate","index","selected","element","getComputedStyle","backgroundColor","toBe","mockReset","getByRole","focus","toHaveBeenCalledTimes","toHaveBeenCalledWith","activeElement","not","toHaveBeenCalled","querySelector","toBeNull","each","direction","toHaveBeenLastCalledWith","mockClear","click","contextMenu"],"sources":["../../../../../src/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.tsx"],"sourcesContent":["import { fireEvent, render, screen, waitFor } from '@testing-library/react';\nimport React from 'react';\nimport { ThemeProvider } from 'styled-components';\nimport { beforeEach, describe, expect, it, vi } from 'vitest';\nimport EmojiPickerEmojis from './EmojiPickerEmojis';\nimport type { Category } from '../../../types/category';\n\nconst fixtures = vi.hoisted(() => ({\n emojis: [\n { emoji: '😀', name: 'grinning face', skin_tone_support: false },\n { emoji: '😃', name: 'smiling face', skin_tone_support: false },\n { emoji: '😄', name: 'laughing face', skin_tone_support: false },\n { emoji: '🐈', name: 'cat', skin_tone_support: false },\n { emoji: '👍', name: 'thumbs up', skin_tone_support: true },\n { emoji: '👎', name: 'thumbs down', skin_tone_support: true },\n { emoji: '👋', name: 'waving hand', skin_tone_support: true },\n { emoji: '🤝', name: 'handshake', skin_tone_support: true },\n ],\n addHistory: vi.fn(),\n history: [] as { emoji: string; name: string; skin_tone_support: boolean }[],\n}));\n\nvi.mock('unicode-emoji-json/data-by-group.json', () => ({\n default: [\n { slug: 'smileys_emotion', emojis: fixtures.emojis },\n { slug: 'people_body', emojis: fixtures.emojis.slice(4) },\n ],\n}));\nvi.mock('unicode-emoji-json/data-by-emoji.json', () => ({\n default: Object.fromEntries(fixtures.emojis.map(({ emoji, ...data }) => [emoji, data])),\n}));\nvi.mock('../../../hooks/emojiHistory', () => ({\n useEmojiHistory: () => ({\n addOrUpdateEmojiInHistory: fixtures.addHistory,\n historyEmojis: fixtures.history.slice(),\n }),\n}));\nvi.mock('@chayns-components/core', async () => {\n const { useRef } = await import('react');\n return {\n ...(await import('../../../../../core/src/hooks/ref')),\n useIsMeasuredClone: () => [false, useRef<HTMLDivElement>(null)] as const,\n };\n});\n\nconst setup = async () => {\n const onSelect = vi.fn();\n const renderPicker = (searchString = '', selectedCategory: Category = 'smileys_emotion') => (\n <ThemeProvider theme={{ 'secondary-102': 'rgb(255, 0, 0)' }}>\n <input aria-label=\"Search\" />\n <EmojiPickerEmojis\n onSelect={onSelect}\n searchString={searchString}\n selectedCategory={selectedCategory}\n />\n </ThemeProvider>\n );\n const view = render(renderPicker());\n await waitFor(() => expect(view.container.querySelectorAll('[data-emoji]')).toHaveLength(8));\n return {\n ...view,\n onSelect,\n update: (search = '', category?: Category) => view.rerender(renderPicker(search, category)),\n };\n};\n\nconst key = (key: string, ctrlKey = false) => fireEvent.keyDown(document, { key, ctrlKey });\nconst navigate = () => {\n for (let index = 0; index < 7; index += 1) key('ArrowRight');\n};\nconst selected = (element: Element) =>\n expect(getComputedStyle(element).backgroundColor).toBe('rgb(255, 0, 0)');\n\nbeforeEach(() => {\n fixtures.addHistory.mockReset();\n fixtures.history = [];\n});\n\ndescribe('EmojiPickerEmojis changing results', () => {\n it('resets to the first result before Enter after narrowing the search', async () => {\n const { onSelect, update } = await setup();\n navigate();\n screen.getByRole('textbox', { name: 'Search' }).focus();\n update('thumbs');\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('👍', true);\n expect(document.activeElement).toBe(screen.getByRole('textbox', { name: 'Search' }));\n });\n\n it('does not select the hint or throw on Enter and Ctrl+Enter without results', async () => {\n const { onSelect, update, container } = await setup();\n navigate();\n update('no-matching-emoji-9284');\n key('Enter');\n key('Enter', true);\n expect(onSelect).not.toHaveBeenCalled();\n expect(container.querySelector('[data-emoji]')).toBeNull();\n expect(container.querySelector('[tabindex=\"0\"]')).toBeNull();\n });\n\n it.each(['thumbs', 'no-matching-emoji-9284'])(\n 'handles every arrow after searching for %s',\n async (search) => {\n const { onSelect, update, container } = await setup();\n navigate();\n update(search);\n for (const direction of ['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'])\n key(direction);\n key('Enter');\n if (search === 'thumbs') {\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('👍', true);\n selected(container.querySelector('[data-emoji=\"👍\"]')!);\n } else expect(onSelect).not.toHaveBeenCalled();\n },\n );\n\n it('recovers after clearing an empty search', async () => {\n const { onSelect, update, container } = await setup();\n navigate();\n update('no-matching-emoji-9284');\n key('ArrowRight');\n update('');\n key('ArrowRight');\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('😃', true);\n selected(container.querySelector('[data-emoji=\"😃\"]')!);\n });\n\n it('resets on category changes and keeps an empty history unselectable', async () => {\n const { onSelect, update } = await setup();\n navigate();\n update('', 'people_body');\n key('Enter');\n expect(onSelect).toHaveBeenLastCalledWith('👍', true);\n onSelect.mockClear();\n update('', 'history');\n key('ArrowRight');\n key('ArrowDown');\n key('Enter');\n expect(onSelect).not.toHaveBeenCalled();\n });\n\n it('uses visible positions for highlight, keyboard selection, and mouse selection including index zero', async () => {\n const { onSelect, update, container } = await setup();\n update('thumbs');\n selected(container.querySelector('[data-emoji=\"👍\"]')!);\n key('ArrowRight');\n selected(container.querySelector('[data-emoji=\"👎\"]')!);\n key('Enter');\n expect(onSelect).toHaveBeenLastCalledWith('👎', true);\n fireEvent.click(container.querySelector('[data-emoji=\"👍\"]')!);\n selected(container.querySelector('[data-emoji=\"👍\"]')!);\n expect(onSelect).toHaveBeenLastCalledWith('👍', false);\n });\n\n it('opens the skin tone popup for the visible right-clicked emoji after filtering', async () => {\n const { update, onSelect, container } = await setup();\n update('thumbs');\n fireEvent.contextMenu(container.querySelector('[data-emoji=\"👎\"]')!);\n selected(container.querySelector('[data-emoji=\"👎\"]')!);\n key('ArrowRight');\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('👎🏼', false);\n });\n\n it('closes a stale popup on result changes and resumes grid controls', async () => {\n const { update, onSelect, container } = await setup();\n update('thumbs');\n key('Enter', true);\n expect(container.querySelector('[data-skin-tone]')).not.toBeNull();\n update('cat');\n expect(container.querySelector('[data-skin-tone]')).toBeNull();\n key('ArrowRight');\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('🐈', true);\n });\n\n it('dismisses the old popup even when its emoji remains in a smaller result list', async () => {\n const { update, onSelect, container } = await setup();\n update('thumbs');\n fireEvent.contextMenu(container.querySelector('[data-emoji=\"👍\"]')!);\n expect(container.querySelector('[data-skin-tone]')).not.toBeNull();\n update('thumbs up');\n expect(container.querySelector('[data-skin-tone]')).toBeNull();\n selected(container.querySelector('[data-emoji=\"👍\"]')!);\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('👍', true);\n });\n\n it('does not carry an unsupported Ctrl+Enter popup request to the next emoji', async () => {\n const { update, onSelect, container } = await setup();\n update('cat');\n key('Enter', true);\n update('thumbs');\n expect(container.querySelector('[data-skin-tone]')).toBeNull();\n key('ArrowRight');\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('👎', true);\n });\n\n it('keeps navigation stable when history is returned as a fresh array', async () => {\n fixtures.history = fixtures.emojis.slice(0, 3);\n const { update, onSelect, container } = await setup();\n update('', 'history');\n key('ArrowRight');\n update('', 'history');\n key('ArrowRight');\n selected(container.querySelector('[data-emoji=\"😄\"]')!);\n expect(container.querySelectorAll('[data-emoji][tabindex=\"0\"]')).toHaveLength(1);\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('😄', true);\n });\n\n it('clears a search popup when returning to history with the same visible emoji', async () => {\n fixtures.history = [fixtures.emojis[4]!];\n const { update, container } = await setup();\n update('thumbs up', 'history');\n key('Enter', true);\n expect(container.querySelector('[data-skin-tone]')).not.toBeNull();\n update('', 'history');\n expect(container.querySelector('[data-skin-tone]')).toBeNull();\n key('Enter', true);\n expect(container.querySelector('[data-skin-tone]')).toBeNull();\n });\n\n it('keeps normal six-column keyboard navigation and history callbacks', async () => {\n const { onSelect, container } = await setup();\n key('ArrowDown');\n selected(container.querySelector('[data-emoji=\"👋\"]')!);\n key('Enter');\n expect(onSelect).toHaveBeenCalledTimes(1);\n expect(onSelect).toHaveBeenCalledWith('👋', true);\n expect(fixtures.addHistory).toHaveBeenCalledTimes(1);\n expect(fixtures.addHistory).toHaveBeenCalledWith({\n emoji: '👋',\n name: 'waving hand',\n skin_tone_support: true,\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
@@ -112,6 +112,7 @@ const Emoji = ({
112
112
  return /*#__PURE__*/React.createElement(StyledEmoji, {
113
113
  ref: emojiRef,
114
114
  $isSelected: isSelected,
115
+ tabIndex: isSelected ? 0 : -1,
115
116
  "data-emoji": emoji,
116
117
  "data-name": name,
117
118
  "data-skin-tone-support": isSkinToneSupported,
@@ -1 +1 @@
1
- {"version":3,"file":"Emoji.js","names":["AnimatePresence","React","useCallback","useEffect","useRef","useState","AnchorAlignment","StyledEmoji","SkinTonePopup","skinTonePopupContentSize","Emoji","emoji","isSelected","name","isSkinToneSupported","onPopupVisibilityChange","onSelect","shouldShowSkinTonePopup","onRightClick","index","emojiList","shouldShowPopup","setShouldShowPopup","skinTonePopupAnchorAlignment","setSkinTonePopupAnchorAlignment","Top","skinTonePopupAnchorOffset","setSkinTonePopupAnchorOffset","skinTonePopupOverlayPosition","setSkinTonePopupOverlayPosition","top","skinTonePopupPosition","setSkinTonePopupPosition","left","emojiRef","handleClick","calculatePopupPosition","current","element","parentElement","height","elementHeight","elementLeft","elementTop","width","elementWidth","getBoundingClientRect","parentHeight","parentLeft","parentTop","parentWidth","scrollTop","anchorAlignment","anchorOffset","maxLeft","minLeft","Bottom","handleContextMenu","event","preventDefault","stopPropagation","handleHidePopup","createElement","ref","$isSelected","className","onClick","onContextMenu","initial","key","onHidePopup","overlayPosition","position","displayName"],"sources":["../../../../../../src/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.tsx"],"sourcesContent":["import { AnimatePresence } from 'motion/react';\nimport React, { FC, MouseEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport { AnchorAlignment } from '../../../../constants/alignment';\nimport { StyledEmoji } from './Emoji.styles';\nimport SkinTonePopup, { SkinTonePopupProps } from './skin-tone-popup/SkinTonePopup';\nimport { skinTonePopupContentSize } from './skin-tone-popup/SkinTonePopup.styles';\n\nexport type EmojiProps = {\n emoji: string;\n isSelected: boolean;\n name: string;\n index: number;\n isSkinToneSupported: boolean;\n onPopupVisibilityChange: (isVisible: boolean) => void;\n onSelect: (emoji: string) => void;\n onRightClick: (newIndex: number) => void;\n shouldShowSkinTonePopup: boolean;\n emojiList: { [x: string]: { skin_tone_support: any } };\n};\n\nconst Emoji: FC<EmojiProps> = ({\n emoji,\n isSelected,\n name,\n isSkinToneSupported,\n onPopupVisibilityChange,\n onSelect,\n shouldShowSkinTonePopup,\n onRightClick,\n index,\n emojiList,\n}) => {\n const [shouldShowPopup, setShouldShowPopup] = useState(false);\n const [skinTonePopupAnchorAlignment, setSkinTonePopupAnchorAlignment] = useState(\n AnchorAlignment.Top,\n );\n const [skinTonePopupAnchorOffset, setSkinTonePopupAnchorOffset] = useState(0);\n const [skinTonePopupOverlayPosition, setSkinTonePopupOverlayPosition] = useState<\n SkinTonePopupProps['overlayPosition']\n >({ top: 0 });\n const [skinTonePopupPosition, setSkinTonePopupPosition] = useState<\n SkinTonePopupProps['position']\n >({ left: 0, top: 0 });\n\n const emojiRef = useRef<HTMLDivElement>(null);\n\n const handleClick = useCallback(() => {\n onSelect(emoji);\n }, [emoji, onSelect]);\n\n const calculatePopupPosition = useCallback(() => {\n if (!emojiRef.current) {\n return;\n }\n\n const element = emojiRef.current;\n const { parentElement } = emojiRef.current;\n\n if (parentElement) {\n const {\n height: elementHeight,\n left: elementLeft,\n top: elementTop,\n width: elementWidth,\n } = element.getBoundingClientRect();\n\n const {\n height: parentHeight,\n left: parentLeft,\n top: parentTop,\n width: parentWidth,\n } = parentElement.getBoundingClientRect();\n\n const { scrollTop } = parentElement;\n\n let anchorAlignment = AnchorAlignment.Top;\n let anchorOffset = 0;\n\n let left =\n elementLeft - parentLeft - skinTonePopupContentSize.width / 2 + elementWidth / 2;\n\n let top = elementTop - parentTop + elementHeight + scrollTop;\n\n const maxLeft = parentWidth - skinTonePopupContentSize.width - 12;\n const minLeft = 12;\n\n if (left < minLeft) {\n anchorOffset = left - minLeft;\n left = minLeft;\n } else if (left > maxLeft) {\n anchorOffset = left - maxLeft;\n left = maxLeft;\n }\n\n if (top + skinTonePopupContentSize.height > parentHeight + scrollTop) {\n anchorAlignment = AnchorAlignment.Bottom;\n top -= elementHeight + skinTonePopupContentSize.height;\n }\n\n if (isSkinToneSupported) {\n setSkinTonePopupAnchorAlignment(anchorAlignment);\n setSkinTonePopupAnchorOffset(anchorOffset);\n setSkinTonePopupPosition({ left, top });\n setSkinTonePopupOverlayPosition({ top: scrollTop });\n setShouldShowPopup(true);\n }\n }\n }, [isSkinToneSupported]);\n\n const handleContextMenu = useCallback(\n (event: MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (isSkinToneSupported) {\n onRightClick(index);\n calculatePopupPosition();\n }\n },\n [calculatePopupPosition, index, isSkinToneSupported, onRightClick],\n );\n\n useEffect(() => {\n if (\n emojiRef.current &&\n shouldShowSkinTonePopup &&\n skinTonePopupPosition.top === 0 &&\n skinTonePopupPosition.left === 0\n ) {\n calculatePopupPosition();\n }\n }, [\n calculatePopupPosition,\n index,\n isSkinToneSupported,\n shouldShowSkinTonePopup,\n skinTonePopupPosition,\n ]);\n\n useEffect(() => {\n if (shouldShowSkinTonePopup) {\n setShouldShowPopup(shouldShowSkinTonePopup);\n }\n }, [shouldShowSkinTonePopup]);\n\n const handleHidePopup = useCallback(() => {\n setShouldShowPopup(false);\n }, []);\n\n useEffect(() => {\n onPopupVisibilityChange(shouldShowPopup);\n }, [onPopupVisibilityChange, shouldShowPopup]);\n\n return (\n <StyledEmoji\n ref={emojiRef}\n $isSelected={isSelected}\n data-emoji={emoji}\n data-name={name}\n data-skin-tone-support={isSkinToneSupported}\n className=\"prevent-lose-focus\"\n onClick={handleClick}\n onContextMenu={handleContextMenu}\n >\n {emoji}\n <AnimatePresence initial={false}>\n {shouldShowPopup && (\n <SkinTonePopup\n anchorAlignment={skinTonePopupAnchorAlignment}\n anchorOffset={skinTonePopupAnchorOffset}\n emoji={emoji}\n key={emoji}\n onHidePopup={handleHidePopup}\n onSelect={onSelect}\n overlayPosition={skinTonePopupOverlayPosition}\n position={skinTonePopupPosition}\n emojiList={emojiList}\n />\n )}\n </AnimatePresence>\n </StyledEmoji>\n );\n};\n\nEmoji.displayName = 'Emoji';\n\nexport default Emoji;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"Emoji.js","names":["AnimatePresence","React","useCallback","useEffect","useRef","useState","AnchorAlignment","StyledEmoji","SkinTonePopup","skinTonePopupContentSize","Emoji","emoji","isSelected","name","isSkinToneSupported","onPopupVisibilityChange","onSelect","shouldShowSkinTonePopup","onRightClick","index","emojiList","shouldShowPopup","setShouldShowPopup","skinTonePopupAnchorAlignment","setSkinTonePopupAnchorAlignment","Top","skinTonePopupAnchorOffset","setSkinTonePopupAnchorOffset","skinTonePopupOverlayPosition","setSkinTonePopupOverlayPosition","top","skinTonePopupPosition","setSkinTonePopupPosition","left","emojiRef","handleClick","calculatePopupPosition","current","element","parentElement","height","elementHeight","elementLeft","elementTop","width","elementWidth","getBoundingClientRect","parentHeight","parentLeft","parentTop","parentWidth","scrollTop","anchorAlignment","anchorOffset","maxLeft","minLeft","Bottom","handleContextMenu","event","preventDefault","stopPropagation","handleHidePopup","createElement","ref","$isSelected","tabIndex","className","onClick","onContextMenu","initial","key","onHidePopup","overlayPosition","position","displayName"],"sources":["../../../../../../src/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.tsx"],"sourcesContent":["import { AnimatePresence } from 'motion/react';\nimport React, { FC, MouseEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport { AnchorAlignment } from '../../../../constants/alignment';\nimport { StyledEmoji } from './Emoji.styles';\nimport SkinTonePopup, { SkinTonePopupProps } from './skin-tone-popup/SkinTonePopup';\nimport { skinTonePopupContentSize } from './skin-tone-popup/SkinTonePopup.styles';\n\nexport type EmojiProps = {\n emoji: string;\n isSelected: boolean;\n name: string;\n index: number;\n isSkinToneSupported: boolean;\n onPopupVisibilityChange: (isVisible: boolean) => void;\n onSelect: (emoji: string) => void;\n onRightClick: (newIndex: number) => void;\n shouldShowSkinTonePopup: boolean;\n emojiList: { [x: string]: { skin_tone_support: any } };\n};\n\nconst Emoji: FC<EmojiProps> = ({\n emoji,\n isSelected,\n name,\n isSkinToneSupported,\n onPopupVisibilityChange,\n onSelect,\n shouldShowSkinTonePopup,\n onRightClick,\n index,\n emojiList,\n}) => {\n const [shouldShowPopup, setShouldShowPopup] = useState(false);\n const [skinTonePopupAnchorAlignment, setSkinTonePopupAnchorAlignment] = useState(\n AnchorAlignment.Top,\n );\n const [skinTonePopupAnchorOffset, setSkinTonePopupAnchorOffset] = useState(0);\n const [skinTonePopupOverlayPosition, setSkinTonePopupOverlayPosition] = useState<\n SkinTonePopupProps['overlayPosition']\n >({ top: 0 });\n const [skinTonePopupPosition, setSkinTonePopupPosition] = useState<\n SkinTonePopupProps['position']\n >({ left: 0, top: 0 });\n\n const emojiRef = useRef<HTMLDivElement>(null);\n\n const handleClick = useCallback(() => {\n onSelect(emoji);\n }, [emoji, onSelect]);\n\n const calculatePopupPosition = useCallback(() => {\n if (!emojiRef.current) {\n return;\n }\n\n const element = emojiRef.current;\n const { parentElement } = emojiRef.current;\n\n if (parentElement) {\n const {\n height: elementHeight,\n left: elementLeft,\n top: elementTop,\n width: elementWidth,\n } = element.getBoundingClientRect();\n\n const {\n height: parentHeight,\n left: parentLeft,\n top: parentTop,\n width: parentWidth,\n } = parentElement.getBoundingClientRect();\n\n const { scrollTop } = parentElement;\n\n let anchorAlignment = AnchorAlignment.Top;\n let anchorOffset = 0;\n\n let left =\n elementLeft - parentLeft - skinTonePopupContentSize.width / 2 + elementWidth / 2;\n\n let top = elementTop - parentTop + elementHeight + scrollTop;\n\n const maxLeft = parentWidth - skinTonePopupContentSize.width - 12;\n const minLeft = 12;\n\n if (left < minLeft) {\n anchorOffset = left - minLeft;\n left = minLeft;\n } else if (left > maxLeft) {\n anchorOffset = left - maxLeft;\n left = maxLeft;\n }\n\n if (top + skinTonePopupContentSize.height > parentHeight + scrollTop) {\n anchorAlignment = AnchorAlignment.Bottom;\n top -= elementHeight + skinTonePopupContentSize.height;\n }\n\n if (isSkinToneSupported) {\n setSkinTonePopupAnchorAlignment(anchorAlignment);\n setSkinTonePopupAnchorOffset(anchorOffset);\n setSkinTonePopupPosition({ left, top });\n setSkinTonePopupOverlayPosition({ top: scrollTop });\n setShouldShowPopup(true);\n }\n }\n }, [isSkinToneSupported]);\n\n const handleContextMenu = useCallback(\n (event: MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (isSkinToneSupported) {\n onRightClick(index);\n calculatePopupPosition();\n }\n },\n [calculatePopupPosition, index, isSkinToneSupported, onRightClick],\n );\n\n useEffect(() => {\n if (\n emojiRef.current &&\n shouldShowSkinTonePopup &&\n skinTonePopupPosition.top === 0 &&\n skinTonePopupPosition.left === 0\n ) {\n calculatePopupPosition();\n }\n }, [\n calculatePopupPosition,\n index,\n isSkinToneSupported,\n shouldShowSkinTonePopup,\n skinTonePopupPosition,\n ]);\n\n useEffect(() => {\n if (shouldShowSkinTonePopup) {\n setShouldShowPopup(shouldShowSkinTonePopup);\n }\n }, [shouldShowSkinTonePopup]);\n\n const handleHidePopup = useCallback(() => {\n setShouldShowPopup(false);\n }, []);\n\n useEffect(() => {\n onPopupVisibilityChange(shouldShowPopup);\n }, [onPopupVisibilityChange, shouldShowPopup]);\n\n return (\n <StyledEmoji\n ref={emojiRef}\n $isSelected={isSelected}\n tabIndex={isSelected ? 0 : -1}\n data-emoji={emoji}\n data-name={name}\n data-skin-tone-support={isSkinToneSupported}\n className=\"prevent-lose-focus\"\n onClick={handleClick}\n onContextMenu={handleContextMenu}\n >\n {emoji}\n <AnimatePresence initial={false}>\n {shouldShowPopup && (\n <SkinTonePopup\n anchorAlignment={skinTonePopupAnchorAlignment}\n anchorOffset={skinTonePopupAnchorOffset}\n emoji={emoji}\n key={emoji}\n onHidePopup={handleHidePopup}\n onSelect={onSelect}\n overlayPosition={skinTonePopupOverlayPosition}\n position={skinTonePopupPosition}\n emojiList={emojiList}\n />\n )}\n </AnimatePresence>\n </StyledEmoji>\n );\n};\n\nEmoji.displayName = 'Emoji';\n\nexport default Emoji;\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,101 @@
1
+ import { useCombinedRefs, useIsMeasuredClone } from '@chayns-components/core';
2
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
3
+ import Emoji from '../emoji/Emoji';
4
+ import { StyledEmojiPickerEmojis, StyledEmojiPickerEmojisNoContentInfo } from '../EmojiPickerEmojis.styles';
5
+ const EMOJIS_PER_ROW = 6;
6
+ const EmojiPickerEmojiList = ({
7
+ emojis,
8
+ emojiList,
9
+ isHistory,
10
+ onSelect
11
+ }) => {
12
+ const [shouldPreventListener, ref] = useIsMeasuredClone();
13
+ const [focusedIndex, setFocusedIndex] = useState(0);
14
+ const [shouldShowSkinTonePopup, setShouldShowSkinTonePopup] = useState(false);
15
+ const emojiRef = useRef(null);
16
+ const shouldPreventEmojiControlsRef = useRef(false);
17
+ const combinedRef = useCombinedRefs(emojiRef, ref);
18
+ const handlePopupVisibilityChange = useCallback(isVisible => {
19
+ setShouldShowSkinTonePopup(isVisible);
20
+ shouldPreventEmojiControlsRef.current = isVisible;
21
+ }, []);
22
+ const handleSelect = useCallback((emoji, index, shouldRestoreInputFocus = false) => {
23
+ setFocusedIndex(index);
24
+ onSelect(emoji, shouldRestoreInputFocus);
25
+ }, [onSelect]);
26
+ useEffect(() => {
27
+ const handleKeyDown = event => {
28
+ if (shouldPreventListener || shouldPreventEmojiControlsRef.current) return;
29
+ const isArrowKey = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key);
30
+ if (!isArrowKey && event.key !== 'Enter') return;
31
+ const container = emojiRef.current;
32
+ const elements = container?.querySelectorAll(':scope > [data-emoji]');
33
+ const currentElement = elements?.[focusedIndex];
34
+ if (event.key === 'Enter') {
35
+ if (!currentElement) return;
36
+ const {
37
+ emoji,
38
+ name,
39
+ skinToneSupport
40
+ } = currentElement.dataset;
41
+ if (!emoji || !name || !skinToneSupport) return;
42
+ if (event.ctrlKey) {
43
+ if (skinToneSupport === 'true') handlePopupVisibilityChange(true);
44
+ return;
45
+ }
46
+ handleSelect({
47
+ emoji,
48
+ name,
49
+ skin_tone_support: skinToneSupport === 'true'
50
+ }, focusedIndex, true);
51
+ return;
52
+ }
53
+ event.preventDefault();
54
+ if (event.ctrlKey || !container || !elements?.length) return;
55
+ let newIndex = currentElement ? focusedIndex : 0;
56
+ if (event.key === 'ArrowUp') newIndex = (newIndex - EMOJIS_PER_ROW) % elements.length;else if (event.key === 'ArrowDown') newIndex = (newIndex + EMOJIS_PER_ROW) % elements.length;else if (event.key === 'ArrowLeft') newIndex = (newIndex - 1) % elements.length;else newIndex = (newIndex + 1) % elements.length;
57
+ if (newIndex < 0) newIndex = elements.length - 1;
58
+ const newElement = elements[newIndex];
59
+ if (!newElement) return;
60
+ setFocusedIndex(newIndex);
61
+ const containerRect = container.getBoundingClientRect();
62
+ const elementRect = newElement.getBoundingClientRect();
63
+ if (elementRect.bottom > containerRect.bottom) {
64
+ container.scrollTop += elementRect.bottom - containerRect.bottom;
65
+ } else if (elementRect.top < containerRect.top) {
66
+ container.scrollTop -= containerRect.top - elementRect.top;
67
+ }
68
+ };
69
+ document.addEventListener('keydown', handleKeyDown);
70
+ return () => document.removeEventListener('keydown', handleKeyDown);
71
+ }, [focusedIndex, handlePopupVisibilityChange, handleSelect, shouldPreventListener]);
72
+ const shouldShowNoContentInfo = emojis.length === 0;
73
+ return /*#__PURE__*/React.createElement(StyledEmojiPickerEmojis, {
74
+ className: "chayns-scrollbar",
75
+ $shouldPreventScroll: shouldShowSkinTonePopup,
76
+ $shouldShowNoContentInfo: shouldShowNoContentInfo,
77
+ ref: combinedRef
78
+ }, emojis.map(({
79
+ emoji,
80
+ name,
81
+ skin_tone_support
82
+ }, index) => /*#__PURE__*/React.createElement(Emoji, {
83
+ key: emoji,
84
+ emoji: emoji,
85
+ name: name,
86
+ index: index,
87
+ isSelected: index === focusedIndex,
88
+ isSkinToneSupported: !isHistory && skin_tone_support,
89
+ shouldShowSkinTonePopup: index === focusedIndex && !isHistory && skin_tone_support && shouldShowSkinTonePopup,
90
+ onRightClick: setFocusedIndex,
91
+ onPopupVisibilityChange: handlePopupVisibilityChange,
92
+ onSelect: selectedEmoji => handleSelect({
93
+ emoji: selectedEmoji,
94
+ name,
95
+ skin_tone_support
96
+ }, index),
97
+ emojiList: emojiList
98
+ })), shouldShowNoContentInfo && /*#__PURE__*/React.createElement(StyledEmojiPickerEmojisNoContentInfo, null, "Hier werden die zuletzt verwendeten Emojis angezeigt, die \xFCber diese Auswahl gew\xE4hlt wurden."));
99
+ };
100
+ export default EmojiPickerEmojiList;
101
+ //# sourceMappingURL=EmojiPickerEmojiList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmojiPickerEmojiList.js","names":["useCombinedRefs","useIsMeasuredClone","React","useCallback","useEffect","useRef","useState","Emoji","StyledEmojiPickerEmojis","StyledEmojiPickerEmojisNoContentInfo","EMOJIS_PER_ROW","EmojiPickerEmojiList","emojis","emojiList","isHistory","onSelect","shouldPreventListener","ref","focusedIndex","setFocusedIndex","shouldShowSkinTonePopup","setShouldShowSkinTonePopup","emojiRef","shouldPreventEmojiControlsRef","combinedRef","handlePopupVisibilityChange","isVisible","current","handleSelect","emoji","index","shouldRestoreInputFocus","handleKeyDown","event","isArrowKey","includes","key","container","elements","querySelectorAll","currentElement","name","skinToneSupport","dataset","ctrlKey","skin_tone_support","preventDefault","length","newIndex","newElement","containerRect","getBoundingClientRect","elementRect","bottom","scrollTop","top","document","addEventListener","removeEventListener","shouldShowNoContentInfo","createElement","className","$shouldPreventScroll","$shouldShowNoContentInfo","map","isSelected","isSkinToneSupported","onRightClick","onPopupVisibilityChange","selectedEmoji"],"sources":["../../../../../../src/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.tsx"],"sourcesContent":["import { useCombinedRefs, useIsMeasuredClone } from '@chayns-components/core';\nimport React, { FC, useCallback, useEffect, useRef, useState } from 'react';\nimport Emoji, { type EmojiProps } from '../emoji/Emoji';\nimport {\n StyledEmojiPickerEmojis,\n StyledEmojiPickerEmojisNoContentInfo,\n} from '../EmojiPickerEmojis.styles';\n\nexport interface PickerEmoji {\n emoji: string;\n name: string;\n skin_tone_support: boolean;\n}\n\ninterface EmojiPickerEmojiListProps {\n emojis: PickerEmoji[];\n emojiList: EmojiProps['emojiList'];\n isHistory: boolean;\n onSelect: (emoji: PickerEmoji, shouldRestoreInputFocus?: boolean) => void;\n}\n\nconst EMOJIS_PER_ROW = 6;\n\nconst EmojiPickerEmojiList: FC<EmojiPickerEmojiListProps> = ({\n emojis,\n emojiList,\n isHistory,\n onSelect,\n}) => {\n const [shouldPreventListener, ref] = useIsMeasuredClone<HTMLDivElement>();\n const [focusedIndex, setFocusedIndex] = useState(0);\n const [shouldShowSkinTonePopup, setShouldShowSkinTonePopup] = useState(false);\n const emojiRef = useRef<HTMLDivElement>(null);\n const shouldPreventEmojiControlsRef = useRef(false);\n const combinedRef = useCombinedRefs(emojiRef, ref);\n\n const handlePopupVisibilityChange = useCallback((isVisible: boolean) => {\n setShouldShowSkinTonePopup(isVisible);\n shouldPreventEmojiControlsRef.current = isVisible;\n }, []);\n\n const handleSelect = useCallback(\n (emoji: PickerEmoji, index: number, shouldRestoreInputFocus = false) => {\n setFocusedIndex(index);\n onSelect(emoji, shouldRestoreInputFocus);\n },\n [onSelect],\n );\n\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (shouldPreventListener || shouldPreventEmojiControlsRef.current) return;\n\n const isArrowKey = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(\n event.key,\n );\n if (!isArrowKey && event.key !== 'Enter') return;\n\n const container = emojiRef.current;\n const elements = container?.querySelectorAll<HTMLDivElement>(':scope > [data-emoji]');\n const currentElement = elements?.[focusedIndex];\n\n if (event.key === 'Enter') {\n if (!currentElement) return;\n\n const { emoji, name, skinToneSupport } = currentElement.dataset;\n if (!emoji || !name || !skinToneSupport) return;\n\n if (event.ctrlKey) {\n if (skinToneSupport === 'true') handlePopupVisibilityChange(true);\n return;\n }\n\n handleSelect(\n { emoji, name, skin_tone_support: skinToneSupport === 'true' },\n focusedIndex,\n true,\n );\n return;\n }\n\n event.preventDefault();\n if (event.ctrlKey || !container || !elements?.length) return;\n\n let newIndex = currentElement ? focusedIndex : 0;\n if (event.key === 'ArrowUp') newIndex = (newIndex - EMOJIS_PER_ROW) % elements.length;\n else if (event.key === 'ArrowDown')\n newIndex = (newIndex + EMOJIS_PER_ROW) % elements.length;\n else if (event.key === 'ArrowLeft') newIndex = (newIndex - 1) % elements.length;\n else newIndex = (newIndex + 1) % elements.length;\n\n if (newIndex < 0) newIndex = elements.length - 1;\n\n const newElement = elements[newIndex];\n if (!newElement) return;\n\n setFocusedIndex(newIndex);\n\n const containerRect = container.getBoundingClientRect();\n const elementRect = newElement.getBoundingClientRect();\n\n if (elementRect.bottom > containerRect.bottom) {\n container.scrollTop += elementRect.bottom - containerRect.bottom;\n } else if (elementRect.top < containerRect.top) {\n container.scrollTop -= containerRect.top - elementRect.top;\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [focusedIndex, handlePopupVisibilityChange, handleSelect, shouldPreventListener]);\n\n const shouldShowNoContentInfo = emojis.length === 0;\n\n return (\n <StyledEmojiPickerEmojis\n className=\"chayns-scrollbar\"\n $shouldPreventScroll={shouldShowSkinTonePopup}\n $shouldShowNoContentInfo={shouldShowNoContentInfo}\n ref={combinedRef}\n >\n {emojis.map(({ emoji, name, skin_tone_support }, index) => (\n <Emoji\n key={emoji}\n emoji={emoji}\n name={name}\n index={index}\n isSelected={index === focusedIndex}\n isSkinToneSupported={!isHistory && skin_tone_support}\n shouldShowSkinTonePopup={\n index === focusedIndex &&\n !isHistory &&\n skin_tone_support &&\n shouldShowSkinTonePopup\n }\n onRightClick={setFocusedIndex}\n onPopupVisibilityChange={handlePopupVisibilityChange}\n onSelect={(selectedEmoji) =>\n handleSelect({ emoji: selectedEmoji, name, skin_tone_support }, index)\n }\n emojiList={emojiList}\n />\n ))}\n {shouldShowNoContentInfo && (\n <StyledEmojiPickerEmojisNoContentInfo>\n Hier werden die zuletzt verwendeten Emojis angezeigt, die über diese Auswahl\n gewählt wurden.\n </StyledEmojiPickerEmojisNoContentInfo>\n )}\n </StyledEmojiPickerEmojis>\n );\n};\n\nexport default EmojiPickerEmojiList;\n"],"mappings":"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","ignoreList":[]}
@@ -141,45 +141,73 @@ export const restoreSelection = element => {
141
141
  selection.addRange(range);
142
142
  range.collapse(true);
143
143
  };
144
- export const insertInvisibleCursorMarker = () => {
145
- const selection = window.getSelection();
146
- if (!selection || selection.rangeCount === 0) {
147
- return;
144
+ const CURSOR_MARKER_DELAY_MS = 10;
145
+ const pendingCursorMarkers = new WeakMap();
146
+ export const insertInvisibleCursorMarker = editorElement => {
147
+ const ownerDocument = editorElement.ownerDocument;
148
+ pendingCursorMarkers.get(ownerDocument)?.();
149
+ const selection = ownerDocument.getSelection();
150
+ if (!selection || selection.rangeCount === 0 || !editorElement.isConnected) {
151
+ return undefined;
152
+ }
153
+ if (!editorElement.contains(selection.getRangeAt(0).startContainer)) {
154
+ return undefined;
148
155
  }
149
- const range = selection.getRangeAt(0);
150
- const textNode = range.startContainer;
151
- const offset = range.startOffset;
152
156
 
153
157
  // noinspection JSDeprecatedSymbols
154
- document.execCommand('delete', false);
155
- const span = document.createElement('span');
158
+ ownerDocument.execCommand('delete', false);
159
+ if (selection.rangeCount === 0) {
160
+ return undefined;
161
+ }
162
+ const {
163
+ startContainer: textNode,
164
+ startOffset: offset
165
+ } = selection.getRangeAt(0);
166
+ const parent = textNode.parentNode;
167
+ if (!parent || !editorElement.contains(textNode) || textNode.nodeType !== Node.TEXT_NODE) {
168
+ return undefined;
169
+ }
170
+ const span = ownerDocument.createElement('span');
156
171
  span.style.display = 'inline-block';
157
172
  span.style.width = '0';
158
173
  span.style.height = '0';
159
174
  span.className = 'invisible-cursor-marker';
160
- const parent = textNode.parentNode;
161
- if (parent) {
162
- if (textNode.nodeType === Node.TEXT_NODE) {
163
- const textContent = textNode.textContent || '';
164
- const beforeText = textContent.slice(0, offset);
165
- const afterText = textContent.slice(offset);
166
- textNode.textContent = beforeText;
167
- parent.insertBefore(span, textNode.nextSibling);
168
- const afterTextNode = document.createTextNode(afterText);
169
- parent.insertBefore(afterTextNode, span.nextSibling);
170
- setTimeout(() => {
171
- // Set cursor to cursor element
172
- const newRange = document.createRange();
173
- newRange.setStartAfter(span);
174
- newRange.setEndAfter(span);
175
- selection.removeAllRanges();
176
- selection.addRange(newRange);
175
+ const textContent = textNode.textContent || '';
176
+ textNode.textContent = textContent.slice(0, offset);
177
+ parent.insertBefore(span, textNode.nextSibling);
178
+ parent.insertBefore(ownerDocument.createTextNode(textContent.slice(offset)), span.nextSibling);
177
179
 
178
- // Remove cursor element
179
- span.remove();
180
- }, 10);
180
+ // Capture the selection after synchronous editing and marker insertion have settled.
181
+ const expectedRange = selection.getRangeAt(0);
182
+ const {
183
+ anchorNode,
184
+ anchorOffset,
185
+ focusNode,
186
+ focusOffset
187
+ } = selection;
188
+ const activeElement = ownerDocument.activeElement;
189
+ const cleanup = () => {
190
+ clearTimeout(timer);
191
+ editorElement.removeEventListener('blur', cleanup, true);
192
+ span.remove();
193
+ if (pendingCursorMarkers.get(ownerDocument) === cleanup) {
194
+ pendingCursorMarkers.delete(ownerDocument);
181
195
  }
182
- }
196
+ };
197
+ const timer = setTimeout(() => {
198
+ const isCurrentSelection = selection.rangeCount > 0 && selection.getRangeAt(0) === expectedRange && selection.anchorNode === anchorNode && selection.anchorOffset === anchorOffset && selection.focusNode === focusNode && selection.focusOffset === focusOffset && ownerDocument.activeElement === activeElement;
199
+ if (span.isConnected && span.parentNode === parent && editorElement.isConnected && editorElement.contains(span) && isCurrentSelection) {
200
+ const newRange = ownerDocument.createRange();
201
+ newRange.setStartAfter(span);
202
+ newRange.collapse(true);
203
+ selection.removeAllRanges();
204
+ selection.addRange(newRange);
205
+ }
206
+ cleanup();
207
+ }, CURSOR_MARKER_DELAY_MS);
208
+ editorElement.addEventListener('blur', cleanup, true);
209
+ pendingCursorMarkers.set(ownerDocument, cleanup);
210
+ return cleanup;
183
211
  };
184
212
  export const insertPseudoMarker = () => {
185
213
  const selection = window.getSelection();
@@ -391,6 +419,7 @@ export const setCursorPositionByAbsIndex = ({
391
419
  editorElement,
392
420
  position
393
421
  }) => {
422
+ pendingCursorMarkers.get(editorElement.ownerDocument)?.();
394
423
  const selection = window.getSelection?.();
395
424
  if (!selection) {
396
425
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"selection.js","names":["clamp","convertHTMLToText","getElementTextLength","childIndex","endOffset","startOffset","saveSelection","element","shouldIgnoreEmptyTextNodes","selection","window","getSelection","anchorNode","range","getRangeAt","childNodesArray","Array","from","childNodes","filter","nodeType","nodeValue","Node","TEXT_NODE","indexOf","restoreSelection","hasFoundNoJoiner","forEach","node","noJoinerIndex","replace","childNode","elementTextLength","nextSibling","charCodeAt","textNode","document","createTextNode","parentNode","insertBefore","length","createRange","setStart","setEnd","error","removeAllRanges","addRange","collapse","insertInvisibleCursorMarker","rangeCount","startContainer","offset","execCommand","span","createElement","style","display","width","height","className","parent","textContent","beforeText","slice","afterText","afterTextNode","setTimeout","newRange","setStartAfter","setEndAfter","remove","insertPseudoMarker","marker","id","insertNode","insertCursorAtMarker","ref","current","querySelector","moveSelectionOffset","distance","setChildIndex","index","getCharCodeThatWillBeDeleted","event","key","previousSibling","endContainer","findAndSelectText","editorElement","searchText","options","shouldReplaceNearCursor","includes","cursorPos","getCurrentCursorPosition","matches","absCounter","searchNodesForText","push","absIndex","nodeName","match","reduce","prev","curr","Math","abs","sel","contains","commonAncestorContainer","pre","selectNodeContents","container","appendChild","cloneContents","bbCodeUntilCursor","innerHTML","preserveSpaces","shouldSerializeNoEmojiToBBCode","getCursorTargetByAbsIndex","position","clampedPosition","searchNodes","nodeText","nextAbsCounter","child","found","rootNode","lastTextNode","lastChild","appendedTextNode","setCursorPositionByAbsIndex","target","unwrapIgnoreEmojiSpanAtCursor","cursorOffset","ELEMENT_NODE","classList","cursorNode","cursorNodeOffset","clonedChild","cloneNode","removeChild","moveCursorOutOfIgnoreEmojiSpan","targetNode","walker","createTreeWalker","NodeFilter","SHOW_TEXT","firstTextNode","nextNode"],"sources":["../../../src/utils/selection.ts"],"sourcesContent":["import type { KeyboardEvent, RefObject } from 'react';\nimport { clamp } from './number';\nimport { convertHTMLToText, getElementTextLength } from './text';\n\nlet childIndex = -1;\nlet endOffset = -1;\nlet startOffset = -1;\n\ninterface SaveSelectionOptions {\n shouldIgnoreEmptyTextNodes?: boolean;\n}\n\nexport const saveSelection = (\n element: HTMLDivElement,\n { shouldIgnoreEmptyTextNodes }: SaveSelectionOptions = {},\n) => {\n const selection = window.getSelection();\n\n if (!selection) {\n return;\n }\n\n const { anchorNode } = selection;\n\n if (!anchorNode) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n\n let childNodesArray = Array.from(element.childNodes);\n\n if (shouldIgnoreEmptyTextNodes) {\n childNodesArray = childNodesArray.filter(\n ({ nodeType, nodeValue }) =>\n nodeType !== Node.TEXT_NODE || (nodeValue !== '' && nodeValue !== '\\u200B'),\n );\n }\n\n childIndex = childNodesArray.indexOf(anchorNode as ChildNode);\n\n endOffset = range.endOffset;\n startOffset = range.startOffset;\n};\n\nexport const restoreSelection = (element: HTMLDivElement) => {\n // Search for \\u200C in child nodes. If found, set the childIndex, startOffset, and endOffset to the\n // position of the \\u200C character. Also remove the \\u200C character from the child node. If not found,\n // the childIndex, startOffset, and endOffset will be like before.\n const childNodesArray = Array.from(element.childNodes);\n\n let hasFoundNoJoiner = false;\n\n childNodesArray.forEach((node) => {\n if (\n !hasFoundNoJoiner &&\n node.nodeType === Node.TEXT_NODE &&\n typeof node.nodeValue === 'string'\n ) {\n const noJoinerIndex = node.nodeValue.indexOf('\\u200C');\n\n if (noJoinerIndex !== -1) {\n hasFoundNoJoiner = true;\n\n childIndex = childNodesArray.indexOf(node);\n startOffset = noJoinerIndex;\n endOffset = noJoinerIndex;\n }\n }\n });\n\n // Remove all no joiner characters from the child nodes if no joiner was found\n if (hasFoundNoJoiner) {\n childNodesArray.forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE && typeof node.nodeValue === 'string') {\n // eslint-disable-next-line no-param-reassign\n node.nodeValue = node.nodeValue.replace(/\\u200C/g, '');\n }\n });\n }\n\n let childNode = element.childNodes[childIndex];\n\n const selection = window.getSelection();\n\n if (!childNode || !element || !selection) {\n return;\n }\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n const elementTextLength = getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else if (childNode.nodeValue && endOffset > childNode.nodeValue.length) {\n if (childNode.nextSibling?.nodeValue) {\n let elementTextLength = childNode.nodeValue.length;\n\n childNode = childNode.nextSibling;\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n elementTextLength += getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling?.nodeValue) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n }\n } else {\n endOffset = childNode.nodeValue.length;\n startOffset = childNode.nodeValue.length;\n }\n }\n\n const range = document.createRange();\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue === 'string') {\n startOffset = clamp(startOffset, 0, childNode.nodeValue.length);\n endOffset = clamp(endOffset, 0, childNode.nodeValue.length);\n }\n\n try {\n range.setStart(childNode, startOffset);\n range.setEnd(childNode, endOffset);\n } catch (error) {\n // Do nothing\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\nexport const insertInvisibleCursorMarker = (): void => {\n const selection = window.getSelection();\n\n if (!selection || selection.rangeCount === 0) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n const textNode = range.startContainer;\n const offset = range.startOffset;\n\n // noinspection JSDeprecatedSymbols\n document.execCommand('delete', false);\n\n const span = document.createElement('span');\n span.style.display = 'inline-block';\n span.style.width = '0';\n span.style.height = '0';\n span.className = 'invisible-cursor-marker';\n\n const parent = textNode.parentNode;\n\n if (parent) {\n if (textNode.nodeType === Node.TEXT_NODE) {\n const textContent = textNode.textContent || '';\n const beforeText = textContent.slice(0, offset);\n const afterText = textContent.slice(offset);\n\n textNode.textContent = beforeText;\n\n parent.insertBefore(span, textNode.nextSibling);\n const afterTextNode = document.createTextNode(afterText);\n parent.insertBefore(afterTextNode, span.nextSibling);\n\n setTimeout(() => {\n // Set cursor to cursor element\n const newRange = document.createRange();\n newRange.setStartAfter(span);\n newRange.setEndAfter(span);\n selection.removeAllRanges();\n selection.addRange(newRange);\n\n // Remove cursor element\n span.remove();\n }, 10);\n }\n }\n};\n\nexport const insertPseudoMarker = () => {\n const selection = window.getSelection();\n\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n const marker = document.createElement('span');\n marker.id = 'cursor-marker';\n marker.style.display = 'inline-block';\n marker.style.width = '0';\n marker.style.height = '0';\n range.insertNode(marker);\n }\n};\n\nexport const insertCursorAtMarker = (ref: RefObject<HTMLDivElement>) => {\n const marker = ref.current?.querySelector('#cursor-marker');\n\n if (marker) {\n const selection = window.getSelection();\n const range = document.createRange();\n range.setStartAfter(marker);\n range.setEndAfter(marker);\n selection?.removeAllRanges();\n selection?.addRange(range);\n marker.remove();\n }\n};\n\nexport const moveSelectionOffset = (distance: number) => {\n endOffset += distance;\n startOffset += distance;\n};\n\nexport const setChildIndex = (index: number) => {\n childIndex = index;\n};\n\n/**\n * This function returns the code of the character that will be removed by the KeyDown event in the\n * next step, if the \"Backspace\" or \"Delete\" key was pressed and there is no selection of multiple\n * characters.\n *\n * @param event - Keyboard event from \"onKeyDown\"\n */\nexport const getCharCodeThatWillBeDeleted = (event: KeyboardEvent<HTMLDivElement>) => {\n const range = window.getSelection()?.getRangeAt(0);\n\n /**\n * At this point the function is aborted if there is no selection range, several characters have\n * been selected and therefore no single letter is removed or neither the \"Backspace\" nor the\n * \"Delete\" key has been pressed.\n */\n if (\n !range ||\n range.endOffset !== range.startOffset ||\n (event.key !== 'Backspace' && event.key !== 'Delete' && event.key !== 'Unidentified')\n ) {\n return null;\n }\n\n if (event.key === 'Backspace' || event.key === 'Unidentified') {\n const { nodeValue, previousSibling } = range.startContainer;\n\n if (range.startOffset > 0) {\n return nodeValue?.charCodeAt(range.startOffset - 1);\n }\n\n return previousSibling?.nodeValue?.charCodeAt(previousSibling.nodeValue.length - 1);\n }\n\n const { nextSibling, nodeValue } = range.endContainer;\n\n if (range.endOffset < (nodeValue?.length ?? 0)) {\n return nodeValue?.charCodeAt(range.endOffset);\n }\n\n return nextSibling?.nodeValue?.charCodeAt(0);\n};\n\nexport type ReplaceTextOptions = { shouldReplaceNearCursor?: boolean };\n\ninterface FindAndSelectTextOptions {\n editorElement: HTMLDivElement;\n searchText: string;\n options?: ReplaceTextOptions;\n}\n\nexport interface SetCursorPositionByAbsIndexOptions {\n editorElement: HTMLDivElement;\n position: number;\n}\n\ntype Match = { node: Node; offset: number; absIndex: number };\n\nexport const findAndSelectText = ({\n editorElement,\n searchText,\n options = { shouldReplaceNearCursor: true },\n}: FindAndSelectTextOptions): Range | null => {\n if (!editorElement.textContent?.includes(searchText)) {\n return null;\n }\n\n const range = document.createRange();\n\n const cursorPos = getCurrentCursorPosition(editorElement);\n\n const matches: Match[] = [];\n let absCounter = 0;\n\n const searchNodesForText = (node: Node) => {\n if (node.nodeType === Node.TEXT_NODE && node.textContent) {\n let index = node.textContent.indexOf(searchText);\n while (index !== -1) {\n matches.push({\n node,\n offset: index,\n absIndex: absCounter + index,\n });\n index = node.textContent.indexOf(searchText, index + 1);\n }\n absCounter += node.textContent.length;\n } else if (node.nodeName !== 'LC_MENTION') {\n Array.from(node.childNodes).forEach(searchNodesForText);\n }\n };\n\n searchNodesForText(editorElement);\n\n if (matches.length === 0) {\n return null;\n }\n\n let match = matches[0];\n\n if (options?.shouldReplaceNearCursor && cursorPos !== null) {\n match = matches.reduce((prev, curr) =>\n Math.abs(curr.absIndex - cursorPos) < Math.abs(prev.absIndex - cursorPos) ? curr : prev,\n );\n }\n\n if (!match) {\n return null;\n }\n\n range.setStart(match.node, match.offset);\n range.setEnd(match.node, match.offset + searchText.length);\n\n return range;\n};\n\nexport const getCurrentCursorPosition = (editorElement: HTMLDivElement | null): number | null => {\n if (!editorElement) {\n return null;\n }\n\n const sel = window.getSelection?.();\n if (!sel || sel.rangeCount === 0) {\n return null;\n }\n\n const range = sel.getRangeAt(0);\n\n if (!editorElement.contains(range.commonAncestorContainer)) {\n return null;\n }\n\n const pre = document.createRange();\n pre.selectNodeContents(editorElement);\n\n try {\n pre.setEnd(range.startContainer, range.startOffset);\n\n const container = document.createElement('div');\n container.appendChild(pre.cloneContents());\n\n const bbCodeUntilCursor = convertHTMLToText(container.innerHTML, {\n preserveSpaces: true,\n shouldSerializeNoEmojiToBBCode: false,\n });\n\n return bbCodeUntilCursor.length;\n } catch {\n return convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length;\n }\n};\n\ntype CursorTarget = { node: Text; offset: number };\n\nconst getCursorTargetByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): CursorTarget | null => {\n const childNodes = Array.from(editorElement.childNodes);\n\n if (childNodes.length === 0) {\n const textNode = document.createTextNode('');\n editorElement.appendChild(textNode);\n\n return { node: textNode, offset: 0 };\n }\n\n const clampedPosition = clamp(\n position,\n 0,\n convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length,\n );\n\n let absCounter = 0;\n\n const searchNodes = (node: Node): CursorTarget | null => {\n if (node.nodeType === Node.TEXT_NODE) {\n const textNode = node as Text;\n const nodeText = textNode.nodeValue ?? '';\n const nextAbsCounter = absCounter + nodeText.length;\n\n if (clampedPosition <= nextAbsCounter) {\n return {\n node: textNode,\n offset: clamp(clampedPosition - absCounter, 0, nodeText.length),\n };\n }\n\n absCounter = nextAbsCounter;\n\n return null;\n }\n\n if (node.nodeName === 'LC_MENTION') {\n return null;\n }\n\n for (const child of Array.from(node.childNodes)) {\n const found = searchNodes(child);\n if (found) {\n return found;\n }\n }\n\n return null;\n };\n\n for (const rootNode of childNodes) {\n const found = searchNodes(rootNode);\n if (found) {\n return found;\n }\n }\n\n const lastTextNode = editorElement.lastChild;\n if (lastTextNode?.nodeType === Node.TEXT_NODE) {\n const textNode = lastTextNode as Text;\n return { node: textNode, offset: textNode.length };\n }\n\n const appendedTextNode = document.createTextNode('\\u200B');\n editorElement.appendChild(appendedTextNode);\n\n return { node: appendedTextNode, offset: appendedTextNode.length };\n};\n\nexport const setCursorPositionByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): void => {\n const selection = window.getSelection?.();\n\n if (!selection) {\n return;\n }\n\n const target = getCursorTargetByAbsIndex({ editorElement, position });\n\n if (!target) {\n return;\n }\n\n const range = document.createRange();\n\n try {\n range.setStart(target.node, target.offset);\n range.setEnd(target.node, target.offset);\n } catch {\n return;\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\n/**\n * Unwraps any no-emoji-convert span that contains the cursor.\n * This removes the span element but keeps its text content, preventing the cursor from getting stuck.\n */\nexport const unwrapIgnoreEmojiSpanAtCursor = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n const cursorOffset = range.startOffset;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, unwrap it\n const span = commonAncestorContainer as Element;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Find which text node contains the cursor\n let cursorNode: Node | null = null;\n const cursorNodeOffset = cursorOffset;\n\n // Get all child nodes of the span\n const childNodes = Array.from(span.childNodes);\n\n // Insert all children before the span and find the cursor node\n childNodes.forEach((child) => {\n const clonedChild = child.cloneNode(true);\n parentNode.insertBefore(clonedChild, span);\n\n // If this is the node that contains the cursor, track it\n if (child === range.startContainer) {\n cursorNode = clonedChild;\n }\n });\n\n // Remove the span\n parentNode.removeChild(span);\n\n // Restore cursor position in the unwrapped content\n if (cursorNode) {\n range.setStart(cursorNode, cursorNodeOffset);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n\n/**\n * Moves the cursor outside of any no-emoji-convert span if it's currently inside one.\n * This prevents the cursor from getting \"stuck\" inside the protection span when typing.\n */\nexport const moveCursorOutOfIgnoreEmojiSpan = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, move cursor to after it\n const span = commonAncestorContainer as Element;\n const { nextSibling } = span;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Always ensure there's a text node AFTER the span\n let targetNode: Text;\n\n if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n // Next sibling is already a text node, use it\n targetNode = nextSibling as Text;\n } else if (nextSibling && nextSibling.nodeType === Node.ELEMENT_NODE) {\n // Next sibling is an element, find first text node in it\n const walker = document.createTreeWalker(nextSibling, NodeFilter.SHOW_TEXT);\n const firstTextNode = walker.nextNode() as Text;\n if (firstTextNode) {\n targetNode = firstTextNode;\n } else {\n // No text node found, create one\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n } else {\n // No next sibling or it's not a text/element node, create a new text node\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n\n // Place cursor at the start of the target node\n range.setStart(targetNode, 0);\n range.collapse(true);\n\n selection.removeAllRanges();\n selection.addRange(range);\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"selection.js","names":["clamp","convertHTMLToText","getElementTextLength","childIndex","endOffset","startOffset","saveSelection","element","shouldIgnoreEmptyTextNodes","selection","window","getSelection","anchorNode","range","getRangeAt","childNodesArray","Array","from","childNodes","filter","nodeType","nodeValue","Node","TEXT_NODE","indexOf","restoreSelection","hasFoundNoJoiner","forEach","node","noJoinerIndex","replace","childNode","elementTextLength","nextSibling","charCodeAt","textNode","document","createTextNode","parentNode","insertBefore","length","createRange","setStart","setEnd","error","removeAllRanges","addRange","collapse","CURSOR_MARKER_DELAY_MS","pendingCursorMarkers","WeakMap","insertInvisibleCursorMarker","editorElement","ownerDocument","get","rangeCount","isConnected","undefined","contains","startContainer","execCommand","offset","parent","span","createElement","style","display","width","height","className","textContent","slice","expectedRange","anchorOffset","focusNode","focusOffset","activeElement","cleanup","clearTimeout","timer","removeEventListener","remove","delete","setTimeout","isCurrentSelection","newRange","setStartAfter","addEventListener","set","insertPseudoMarker","marker","id","insertNode","insertCursorAtMarker","ref","current","querySelector","setEndAfter","moveSelectionOffset","distance","setChildIndex","index","getCharCodeThatWillBeDeleted","event","key","previousSibling","endContainer","findAndSelectText","searchText","options","shouldReplaceNearCursor","includes","cursorPos","getCurrentCursorPosition","matches","absCounter","searchNodesForText","push","absIndex","nodeName","match","reduce","prev","curr","Math","abs","sel","commonAncestorContainer","pre","selectNodeContents","container","appendChild","cloneContents","bbCodeUntilCursor","innerHTML","preserveSpaces","shouldSerializeNoEmojiToBBCode","getCursorTargetByAbsIndex","position","clampedPosition","searchNodes","nodeText","nextAbsCounter","child","found","rootNode","lastTextNode","lastChild","appendedTextNode","setCursorPositionByAbsIndex","target","unwrapIgnoreEmojiSpanAtCursor","cursorOffset","ELEMENT_NODE","classList","cursorNode","cursorNodeOffset","clonedChild","cloneNode","removeChild","moveCursorOutOfIgnoreEmojiSpan","targetNode","walker","createTreeWalker","NodeFilter","SHOW_TEXT","firstTextNode","nextNode"],"sources":["../../../src/utils/selection.ts"],"sourcesContent":["import type { KeyboardEvent, RefObject } from 'react';\nimport { clamp } from './number';\nimport { convertHTMLToText, getElementTextLength } from './text';\n\nlet childIndex = -1;\nlet endOffset = -1;\nlet startOffset = -1;\n\ninterface SaveSelectionOptions {\n shouldIgnoreEmptyTextNodes?: boolean;\n}\n\nexport const saveSelection = (\n element: HTMLDivElement,\n { shouldIgnoreEmptyTextNodes }: SaveSelectionOptions = {},\n) => {\n const selection = window.getSelection();\n\n if (!selection) {\n return;\n }\n\n const { anchorNode } = selection;\n\n if (!anchorNode) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n\n let childNodesArray = Array.from(element.childNodes);\n\n if (shouldIgnoreEmptyTextNodes) {\n childNodesArray = childNodesArray.filter(\n ({ nodeType, nodeValue }) =>\n nodeType !== Node.TEXT_NODE || (nodeValue !== '' && nodeValue !== '\\u200B'),\n );\n }\n\n childIndex = childNodesArray.indexOf(anchorNode as ChildNode);\n\n endOffset = range.endOffset;\n startOffset = range.startOffset;\n};\n\nexport const restoreSelection = (element: HTMLDivElement) => {\n // Search for \\u200C in child nodes. If found, set the childIndex, startOffset, and endOffset to the\n // position of the \\u200C character. Also remove the \\u200C character from the child node. If not found,\n // the childIndex, startOffset, and endOffset will be like before.\n const childNodesArray = Array.from(element.childNodes);\n\n let hasFoundNoJoiner = false;\n\n childNodesArray.forEach((node) => {\n if (\n !hasFoundNoJoiner &&\n node.nodeType === Node.TEXT_NODE &&\n typeof node.nodeValue === 'string'\n ) {\n const noJoinerIndex = node.nodeValue.indexOf('\\u200C');\n\n if (noJoinerIndex !== -1) {\n hasFoundNoJoiner = true;\n\n childIndex = childNodesArray.indexOf(node);\n startOffset = noJoinerIndex;\n endOffset = noJoinerIndex;\n }\n }\n });\n\n // Remove all no joiner characters from the child nodes if no joiner was found\n if (hasFoundNoJoiner) {\n childNodesArray.forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE && typeof node.nodeValue === 'string') {\n // eslint-disable-next-line no-param-reassign\n node.nodeValue = node.nodeValue.replace(/\\u200C/g, '');\n }\n });\n }\n\n let childNode = element.childNodes[childIndex];\n\n const selection = window.getSelection();\n\n if (!childNode || !element || !selection) {\n return;\n }\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n const elementTextLength = getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else if (childNode.nodeValue && endOffset > childNode.nodeValue.length) {\n if (childNode.nextSibling?.nodeValue) {\n let elementTextLength = childNode.nodeValue.length;\n\n childNode = childNode.nextSibling;\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue !== 'string') {\n elementTextLength += getElementTextLength(childNode as Element);\n\n if (childNode.nextSibling?.nodeValue) {\n childNode = childNode.nextSibling;\n\n if (childNode.nodeType === Node.TEXT_NODE && childNode.nodeValue) {\n endOffset -= elementTextLength;\n startOffset -= elementTextLength;\n\n if (childNode.nodeValue.charCodeAt(endOffset) === 8203) {\n endOffset += 1;\n startOffset += 1;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n } else {\n const textNode = document.createTextNode('\\u200B');\n\n childNode.parentNode?.insertBefore(textNode, childNode.nextSibling);\n\n childNode = textNode;\n\n endOffset = textNode.length;\n startOffset = textNode.length;\n }\n }\n } else {\n endOffset = childNode.nodeValue.length;\n startOffset = childNode.nodeValue.length;\n }\n }\n\n const range = document.createRange();\n\n // noinspection SuspiciousTypeOfGuard\n if (typeof childNode.nodeValue === 'string') {\n startOffset = clamp(startOffset, 0, childNode.nodeValue.length);\n endOffset = clamp(endOffset, 0, childNode.nodeValue.length);\n }\n\n try {\n range.setStart(childNode, startOffset);\n range.setEnd(childNode, endOffset);\n } catch (error) {\n // Do nothing\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\nconst CURSOR_MARKER_DELAY_MS = 10;\nconst pendingCursorMarkers = new WeakMap<Document, VoidFunction>();\n\nexport const insertInvisibleCursorMarker = (\n editorElement: HTMLDivElement,\n): VoidFunction | undefined => {\n const ownerDocument = editorElement.ownerDocument;\n pendingCursorMarkers.get(ownerDocument)?.();\n\n const selection = ownerDocument.getSelection();\n\n if (!selection || selection.rangeCount === 0 || !editorElement.isConnected) {\n return undefined;\n }\n\n if (!editorElement.contains(selection.getRangeAt(0).startContainer)) {\n return undefined;\n }\n\n // noinspection JSDeprecatedSymbols\n ownerDocument.execCommand('delete', false);\n\n if (selection.rangeCount === 0) {\n return undefined;\n }\n\n const { startContainer: textNode, startOffset: offset } = selection.getRangeAt(0);\n const parent = textNode.parentNode;\n\n if (!parent || !editorElement.contains(textNode) || textNode.nodeType !== Node.TEXT_NODE) {\n return undefined;\n }\n\n const span = ownerDocument.createElement('span');\n span.style.display = 'inline-block';\n span.style.width = '0';\n span.style.height = '0';\n span.className = 'invisible-cursor-marker';\n\n const textContent = textNode.textContent || '';\n textNode.textContent = textContent.slice(0, offset);\n parent.insertBefore(span, textNode.nextSibling);\n parent.insertBefore(ownerDocument.createTextNode(textContent.slice(offset)), span.nextSibling);\n\n // Capture the selection after synchronous editing and marker insertion have settled.\n const expectedRange = selection.getRangeAt(0);\n const { anchorNode, anchorOffset, focusNode, focusOffset } = selection;\n const activeElement = ownerDocument.activeElement;\n\n const cleanup = () => {\n clearTimeout(timer);\n editorElement.removeEventListener('blur', cleanup, true);\n span.remove();\n\n if (pendingCursorMarkers.get(ownerDocument) === cleanup) {\n pendingCursorMarkers.delete(ownerDocument);\n }\n };\n\n const timer = setTimeout(() => {\n const isCurrentSelection =\n selection.rangeCount > 0 &&\n selection.getRangeAt(0) === expectedRange &&\n selection.anchorNode === anchorNode &&\n selection.anchorOffset === anchorOffset &&\n selection.focusNode === focusNode &&\n selection.focusOffset === focusOffset &&\n ownerDocument.activeElement === activeElement;\n\n if (\n span.isConnected &&\n span.parentNode === parent &&\n editorElement.isConnected &&\n editorElement.contains(span) &&\n isCurrentSelection\n ) {\n const newRange = ownerDocument.createRange();\n newRange.setStartAfter(span);\n newRange.collapse(true);\n selection.removeAllRanges();\n selection.addRange(newRange);\n }\n\n cleanup();\n }, CURSOR_MARKER_DELAY_MS);\n\n editorElement.addEventListener('blur', cleanup, true);\n pendingCursorMarkers.set(ownerDocument, cleanup);\n\n return cleanup;\n};\n\nexport const insertPseudoMarker = () => {\n const selection = window.getSelection();\n\n if (selection && selection.rangeCount > 0) {\n const range = selection.getRangeAt(0);\n const marker = document.createElement('span');\n marker.id = 'cursor-marker';\n marker.style.display = 'inline-block';\n marker.style.width = '0';\n marker.style.height = '0';\n range.insertNode(marker);\n }\n};\n\nexport const insertCursorAtMarker = (ref: RefObject<HTMLDivElement>) => {\n const marker = ref.current?.querySelector('#cursor-marker');\n\n if (marker) {\n const selection = window.getSelection();\n const range = document.createRange();\n range.setStartAfter(marker);\n range.setEndAfter(marker);\n selection?.removeAllRanges();\n selection?.addRange(range);\n marker.remove();\n }\n};\n\nexport const moveSelectionOffset = (distance: number) => {\n endOffset += distance;\n startOffset += distance;\n};\n\nexport const setChildIndex = (index: number) => {\n childIndex = index;\n};\n\n/**\n * This function returns the code of the character that will be removed by the KeyDown event in the\n * next step, if the \"Backspace\" or \"Delete\" key was pressed and there is no selection of multiple\n * characters.\n *\n * @param event - Keyboard event from \"onKeyDown\"\n */\nexport const getCharCodeThatWillBeDeleted = (event: KeyboardEvent<HTMLDivElement>) => {\n const range = window.getSelection()?.getRangeAt(0);\n\n /**\n * At this point the function is aborted if there is no selection range, several characters have\n * been selected and therefore no single letter is removed or neither the \"Backspace\" nor the\n * \"Delete\" key has been pressed.\n */\n if (\n !range ||\n range.endOffset !== range.startOffset ||\n (event.key !== 'Backspace' && event.key !== 'Delete' && event.key !== 'Unidentified')\n ) {\n return null;\n }\n\n if (event.key === 'Backspace' || event.key === 'Unidentified') {\n const { nodeValue, previousSibling } = range.startContainer;\n\n if (range.startOffset > 0) {\n return nodeValue?.charCodeAt(range.startOffset - 1);\n }\n\n return previousSibling?.nodeValue?.charCodeAt(previousSibling.nodeValue.length - 1);\n }\n\n const { nextSibling, nodeValue } = range.endContainer;\n\n if (range.endOffset < (nodeValue?.length ?? 0)) {\n return nodeValue?.charCodeAt(range.endOffset);\n }\n\n return nextSibling?.nodeValue?.charCodeAt(0);\n};\n\nexport type ReplaceTextOptions = { shouldReplaceNearCursor?: boolean };\n\ninterface FindAndSelectTextOptions {\n editorElement: HTMLDivElement;\n searchText: string;\n options?: ReplaceTextOptions;\n}\n\nexport interface SetCursorPositionByAbsIndexOptions {\n editorElement: HTMLDivElement;\n position: number;\n}\n\ntype Match = { node: Node; offset: number; absIndex: number };\n\nexport const findAndSelectText = ({\n editorElement,\n searchText,\n options = { shouldReplaceNearCursor: true },\n}: FindAndSelectTextOptions): Range | null => {\n if (!editorElement.textContent?.includes(searchText)) {\n return null;\n }\n\n const range = document.createRange();\n\n const cursorPos = getCurrentCursorPosition(editorElement);\n\n const matches: Match[] = [];\n let absCounter = 0;\n\n const searchNodesForText = (node: Node) => {\n if (node.nodeType === Node.TEXT_NODE && node.textContent) {\n let index = node.textContent.indexOf(searchText);\n while (index !== -1) {\n matches.push({\n node,\n offset: index,\n absIndex: absCounter + index,\n });\n index = node.textContent.indexOf(searchText, index + 1);\n }\n absCounter += node.textContent.length;\n } else if (node.nodeName !== 'LC_MENTION') {\n Array.from(node.childNodes).forEach(searchNodesForText);\n }\n };\n\n searchNodesForText(editorElement);\n\n if (matches.length === 0) {\n return null;\n }\n\n let match = matches[0];\n\n if (options?.shouldReplaceNearCursor && cursorPos !== null) {\n match = matches.reduce((prev, curr) =>\n Math.abs(curr.absIndex - cursorPos) < Math.abs(prev.absIndex - cursorPos) ? curr : prev,\n );\n }\n\n if (!match) {\n return null;\n }\n\n range.setStart(match.node, match.offset);\n range.setEnd(match.node, match.offset + searchText.length);\n\n return range;\n};\n\nexport const getCurrentCursorPosition = (editorElement: HTMLDivElement | null): number | null => {\n if (!editorElement) {\n return null;\n }\n\n const sel = window.getSelection?.();\n if (!sel || sel.rangeCount === 0) {\n return null;\n }\n\n const range = sel.getRangeAt(0);\n\n if (!editorElement.contains(range.commonAncestorContainer)) {\n return null;\n }\n\n const pre = document.createRange();\n pre.selectNodeContents(editorElement);\n\n try {\n pre.setEnd(range.startContainer, range.startOffset);\n\n const container = document.createElement('div');\n container.appendChild(pre.cloneContents());\n\n const bbCodeUntilCursor = convertHTMLToText(container.innerHTML, {\n preserveSpaces: true,\n shouldSerializeNoEmojiToBBCode: false,\n });\n\n return bbCodeUntilCursor.length;\n } catch {\n return convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length;\n }\n};\n\ntype CursorTarget = { node: Text; offset: number };\n\nconst getCursorTargetByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): CursorTarget | null => {\n const childNodes = Array.from(editorElement.childNodes);\n\n if (childNodes.length === 0) {\n const textNode = document.createTextNode('');\n editorElement.appendChild(textNode);\n\n return { node: textNode, offset: 0 };\n }\n\n const clampedPosition = clamp(\n position,\n 0,\n convertHTMLToText(editorElement.innerHTML, {\n shouldSerializeNoEmojiToBBCode: false,\n }).length,\n );\n\n let absCounter = 0;\n\n const searchNodes = (node: Node): CursorTarget | null => {\n if (node.nodeType === Node.TEXT_NODE) {\n const textNode = node as Text;\n const nodeText = textNode.nodeValue ?? '';\n const nextAbsCounter = absCounter + nodeText.length;\n\n if (clampedPosition <= nextAbsCounter) {\n return {\n node: textNode,\n offset: clamp(clampedPosition - absCounter, 0, nodeText.length),\n };\n }\n\n absCounter = nextAbsCounter;\n\n return null;\n }\n\n if (node.nodeName === 'LC_MENTION') {\n return null;\n }\n\n for (const child of Array.from(node.childNodes)) {\n const found = searchNodes(child);\n if (found) {\n return found;\n }\n }\n\n return null;\n };\n\n for (const rootNode of childNodes) {\n const found = searchNodes(rootNode);\n if (found) {\n return found;\n }\n }\n\n const lastTextNode = editorElement.lastChild;\n if (lastTextNode?.nodeType === Node.TEXT_NODE) {\n const textNode = lastTextNode as Text;\n return { node: textNode, offset: textNode.length };\n }\n\n const appendedTextNode = document.createTextNode('\\u200B');\n editorElement.appendChild(appendedTextNode);\n\n return { node: appendedTextNode, offset: appendedTextNode.length };\n};\n\nexport const setCursorPositionByAbsIndex = ({\n editorElement,\n position,\n}: SetCursorPositionByAbsIndexOptions): void => {\n pendingCursorMarkers.get(editorElement.ownerDocument)?.();\n\n const selection = window.getSelection?.();\n\n if (!selection) {\n return;\n }\n\n const target = getCursorTargetByAbsIndex({ editorElement, position });\n\n if (!target) {\n return;\n }\n\n const range = document.createRange();\n\n try {\n range.setStart(target.node, target.offset);\n range.setEnd(target.node, target.offset);\n } catch {\n return;\n }\n\n selection.removeAllRanges();\n selection.addRange(range);\n\n range.collapse(true);\n};\n\n/**\n * Unwraps any no-emoji-convert span that contains the cursor.\n * This removes the span element but keeps its text content, preventing the cursor from getting stuck.\n */\nexport const unwrapIgnoreEmojiSpanAtCursor = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n const cursorOffset = range.startOffset;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, unwrap it\n const span = commonAncestorContainer as Element;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Find which text node contains the cursor\n let cursorNode: Node | null = null;\n const cursorNodeOffset = cursorOffset;\n\n // Get all child nodes of the span\n const childNodes = Array.from(span.childNodes);\n\n // Insert all children before the span and find the cursor node\n childNodes.forEach((child) => {\n const clonedChild = child.cloneNode(true);\n parentNode.insertBefore(clonedChild, span);\n\n // If this is the node that contains the cursor, track it\n if (child === range.startContainer) {\n cursorNode = clonedChild;\n }\n });\n\n // Remove the span\n parentNode.removeChild(span);\n\n // Restore cursor position in the unwrapped content\n if (cursorNode) {\n range.setStart(cursorNode, cursorNodeOffset);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n\n/**\n * Moves the cursor outside of any no-emoji-convert span if it's currently inside one.\n * This prevents the cursor from getting \"stuck\" inside the protection span when typing.\n */\nexport const moveCursorOutOfIgnoreEmojiSpan = (editorElement: HTMLDivElement | null) => {\n if (!editorElement) {\n return;\n }\n\n const selection = window.getSelection();\n\n if (!selection || !selection.rangeCount) {\n return;\n }\n\n const range = selection.getRangeAt(0);\n let { commonAncestorContainer } = range;\n\n if (!editorElement.contains(commonAncestorContainer)) {\n return;\n }\n\n // Walk up the DOM tree to find if we're inside a no-emoji-convert span\n while (commonAncestorContainer && commonAncestorContainer !== editorElement) {\n if (\n commonAncestorContainer.nodeType === Node.ELEMENT_NODE &&\n (commonAncestorContainer as Element).classList.contains('no-emoji-convert')\n ) {\n // We're inside a no-emoji-convert span, move cursor to after it\n const span = commonAncestorContainer as Element;\n const { nextSibling } = span;\n const { parentNode } = span;\n\n if (!parentNode) {\n return;\n }\n\n // Always ensure there's a text node AFTER the span\n let targetNode: Text;\n\n if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {\n // Next sibling is already a text node, use it\n targetNode = nextSibling as Text;\n } else if (nextSibling && nextSibling.nodeType === Node.ELEMENT_NODE) {\n // Next sibling is an element, find first text node in it\n const walker = document.createTreeWalker(nextSibling, NodeFilter.SHOW_TEXT);\n const firstTextNode = walker.nextNode() as Text;\n if (firstTextNode) {\n targetNode = firstTextNode;\n } else {\n // No text node found, create one\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n } else {\n // No next sibling or it's not a text/element node, create a new text node\n targetNode = document.createTextNode('\\u200B');\n parentNode.insertBefore(targetNode, nextSibling);\n }\n\n // Place cursor at the start of the target node\n range.setStart(targetNode, 0);\n range.collapse(true);\n\n selection.removeAllRanges();\n selection.addRange(range);\n break;\n }\n\n // @ts-expect-error - is needed\n commonAncestorContainer = commonAncestorContainer.parentNode;\n }\n};\n"],"mappings":"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","ignoreList":[]}