@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.
- package/lib/cjs/build.test.js +34 -0
- package/lib/cjs/build.test.js.map +1 -0
- package/lib/cjs/components/emoji-input/EmojiInput.js +8 -1
- package/lib/cjs/components/emoji-input/EmojiInput.js.map +1 -1
- package/lib/cjs/components/emoji-input/EmojiInput.test.js +120 -0
- package/lib/cjs/components/emoji-input/EmojiInput.test.js.map +1 -0
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js +48 -219
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js.map +1 -1
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js +316 -0
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js.map +1 -0
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js +1 -0
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js.map +1 -1
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js +109 -0
- package/lib/cjs/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js.map +1 -0
- package/lib/cjs/utils/selection.js +61 -31
- package/lib/cjs/utils/selection.js.map +1 -1
- package/lib/cjs/utils/selection.test.js +160 -0
- package/lib/cjs/utils/selection.test.js.map +1 -0
- package/lib/esm/build.test.js +32 -0
- package/lib/esm/build.test.js.map +1 -0
- package/lib/esm/components/emoji-input/EmojiInput.js +4 -1
- package/lib/esm/components/emoji-input/EmojiInput.js.map +1 -1
- package/lib/esm/components/emoji-input/EmojiInput.test.js +116 -0
- package/lib/esm/components/emoji-input/EmojiInput.test.js.map +1 -0
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js +47 -218
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.js.map +1 -1
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js +312 -0
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/EmojiPickerEmojis.test.js.map +1 -0
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js +1 -0
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji/Emoji.js.map +1 -1
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js +101 -0
- package/lib/esm/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.js.map +1 -0
- package/lib/esm/utils/selection.js +59 -30
- package/lib/esm/utils/selection.js.map +1 -1
- package/lib/esm/utils/selection.test.js +158 -0
- package/lib/esm/utils/selection.test.js.map +1 -0
- package/lib/types/components/emoji-picker/emoji-picker-emojis/emoji-picker-emoji-list/EmojiPickerEmojiList.d.ts +15 -0
- package/lib/types/utils/selection.d.ts +1 -1
- package/package.json +3 -3
- package/lib/types/utils/emoji.test.d.ts +0 -1
- 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":"AAAA,SAASA,eAAe,EAAEC,kBAAkB,QAAQ,yBAAyB;AAC7E,OAAOC,KAAK,IAAQC,WAAW,EAAEC,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAC3E,OAAOC,KAAK,MAA2B,gBAAgB;AACvD,SACIC,uBAAuB,EACvBC,oCAAoC,QACjC,6BAA6B;AAepC,MAAMC,cAAc,GAAG,CAAC;AAExB,MAAMC,oBAAmD,GAAGA,CAAC;EACzDC,MAAM;EACNC,SAAS;EACTC,SAAS;EACTC;AACJ,CAAC,KAAK;EACF,MAAM,CAACC,qBAAqB,EAAEC,GAAG,CAAC,GAAGhB,kBAAkB,CAAiB,CAAC;EACzE,MAAM,CAACiB,YAAY,EAAEC,eAAe,CAAC,GAAGb,QAAQ,CAAC,CAAC,CAAC;EACnD,MAAM,CAACc,uBAAuB,EAAEC,0BAA0B,CAAC,GAAGf,QAAQ,CAAC,KAAK,CAAC;EAC7E,MAAMgB,QAAQ,GAAGjB,MAAM,CAAiB,IAAI,CAAC;EAC7C,MAAMkB,6BAA6B,GAAGlB,MAAM,CAAC,KAAK,CAAC;EACnD,MAAMmB,WAAW,GAAGxB,eAAe,CAACsB,QAAQ,EAAEL,GAAG,CAAC;EAElD,MAAMQ,2BAA2B,GAAGtB,WAAW,CAAEuB,SAAkB,IAAK;IACpEL,0BAA0B,CAACK,SAAS,CAAC;IACrCH,6BAA6B,CAACI,OAAO,GAAGD,SAAS;EACrD,CAAC,EAAE,EAAE,CAAC;EAEN,MAAME,YAAY,GAAGzB,WAAW,CAC5B,CAAC0B,KAAkB,EAAEC,KAAa,EAAEC,uBAAuB,GAAG,KAAK,KAAK;IACpEZ,eAAe,CAACW,KAAK,CAAC;IACtBf,QAAQ,CAACc,KAAK,EAAEE,uBAAuB,CAAC;EAC5C,CAAC,EACD,CAAChB,QAAQ,CACb,CAAC;EAEDX,SAAS,CAAC,MAAM;IACZ,MAAM4B,aAAa,GAAIC,KAAoB,IAAK;MAC5C,IAAIjB,qBAAqB,IAAIO,6BAA6B,CAACI,OAAO,EAAE;MAEpE,MAAMO,UAAU,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,CAAC,CAACC,QAAQ,CAC3EF,KAAK,CAACG,GACV,CAAC;MACD,IAAI,CAACF,UAAU,IAAID,KAAK,CAACG,GAAG,KAAK,OAAO,EAAE;MAE1C,MAAMC,SAAS,GAAGf,QAAQ,CAACK,OAAO;MAClC,MAAMW,QAAQ,GAAGD,SAAS,EAAEE,gBAAgB,CAAiB,uBAAuB,CAAC;MACrF,MAAMC,cAAc,GAAGF,QAAQ,GAAGpB,YAAY,CAAC;MAE/C,IAAIe,KAAK,CAACG,GAAG,KAAK,OAAO,EAAE;QACvB,IAAI,CAACI,cAAc,EAAE;QAErB,MAAM;UAAEX,KAAK;UAAEY,IAAI;UAAEC;QAAgB,CAAC,GAAGF,cAAc,CAACG,OAAO;QAC/D,IAAI,CAACd,KAAK,IAAI,CAACY,IAAI,IAAI,CAACC,eAAe,EAAE;QAEzC,IAAIT,KAAK,CAACW,OAAO,EAAE;UACf,IAAIF,eAAe,KAAK,MAAM,EAAEjB,2BAA2B,CAAC,IAAI,CAAC;UACjE;QACJ;QAEAG,YAAY,CACR;UAAEC,KAAK;UAAEY,IAAI;UAAEI,iBAAiB,EAAEH,eAAe,KAAK;QAAO,CAAC,EAC9DxB,YAAY,EACZ,IACJ,CAAC;QACD;MACJ;MAEAe,KAAK,CAACa,cAAc,CAAC,CAAC;MACtB,IAAIb,KAAK,CAACW,OAAO,IAAI,CAACP,SAAS,IAAI,CAACC,QAAQ,EAAES,MAAM,EAAE;MAEtD,IAAIC,QAAQ,GAAGR,cAAc,GAAGtB,YAAY,GAAG,CAAC;MAChD,IAAIe,KAAK,CAACG,GAAG,KAAK,SAAS,EAAEY,QAAQ,GAAG,CAACA,QAAQ,GAAGtC,cAAc,IAAI4B,QAAQ,CAACS,MAAM,CAAC,KACjF,IAAId,KAAK,CAACG,GAAG,KAAK,WAAW,EAC9BY,QAAQ,GAAG,CAACA,QAAQ,GAAGtC,cAAc,IAAI4B,QAAQ,CAACS,MAAM,CAAC,KACxD,IAAId,KAAK,CAACG,GAAG,KAAK,WAAW,EAAEY,QAAQ,GAAG,CAACA,QAAQ,GAAG,CAAC,IAAIV,QAAQ,CAACS,MAAM,CAAC,KAC3EC,QAAQ,GAAG,CAACA,QAAQ,GAAG,CAAC,IAAIV,QAAQ,CAACS,MAAM;MAEhD,IAAIC,QAAQ,GAAG,CAAC,EAAEA,QAAQ,GAAGV,QAAQ,CAACS,MAAM,GAAG,CAAC;MAEhD,MAAME,UAAU,GAAGX,QAAQ,CAACU,QAAQ,CAAC;MACrC,IAAI,CAACC,UAAU,EAAE;MAEjB9B,eAAe,CAAC6B,QAAQ,CAAC;MAEzB,MAAME,aAAa,GAAGb,SAAS,CAACc,qBAAqB,CAAC,CAAC;MACvD,MAAMC,WAAW,GAAGH,UAAU,CAACE,qBAAqB,CAAC,CAAC;MAEtD,IAAIC,WAAW,CAACC,MAAM,GAAGH,aAAa,CAACG,MAAM,EAAE;QAC3ChB,SAAS,CAACiB,SAAS,IAAIF,WAAW,CAACC,MAAM,GAAGH,aAAa,CAACG,MAAM;MACpE,CAAC,MAAM,IAAID,WAAW,CAACG,GAAG,GAAGL,aAAa,CAACK,GAAG,EAAE;QAC5ClB,SAAS,CAACiB,SAAS,IAAIJ,aAAa,CAACK,GAAG,GAAGH,WAAW,CAACG,GAAG;MAC9D;IACJ,CAAC;IAEDC,QAAQ,CAACC,gBAAgB,CAAC,SAAS,EAAEzB,aAAa,CAAC;IACnD,OAAO,MAAMwB,QAAQ,CAACE,mBAAmB,CAAC,SAAS,EAAE1B,aAAa,CAAC;EACvE,CAAC,EAAE,CAACd,YAAY,EAAEO,2BAA2B,EAAEG,YAAY,EAAEZ,qBAAqB,CAAC,CAAC;EAEpF,MAAM2C,uBAAuB,GAAG/C,MAAM,CAACmC,MAAM,KAAK,CAAC;EAEnD,oBACI7C,KAAA,CAAA0D,aAAA,CAACpD,uBAAuB;IACpBqD,SAAS,EAAC,kBAAkB;IAC5BC,oBAAoB,EAAE1C,uBAAwB;IAC9C2C,wBAAwB,EAAEJ,uBAAwB;IAClD1C,GAAG,EAAEO;EAAY,GAEhBZ,MAAM,CAACoD,GAAG,CAAC,CAAC;IAAEnC,KAAK;IAAEY,IAAI;IAAEI;EAAkB,CAAC,EAAEf,KAAK,kBAClD5B,KAAA,CAAA0D,aAAA,CAACrD,KAAK;IACF6B,GAAG,EAAEP,KAAM;IACXA,KAAK,EAAEA,KAAM;IACbY,IAAI,EAAEA,IAAK;IACXX,KAAK,EAAEA,KAAM;IACbmC,UAAU,EAAEnC,KAAK,KAAKZ,YAAa;IACnCgD,mBAAmB,EAAE,CAACpD,SAAS,IAAI+B,iBAAkB;IACrDzB,uBAAuB,EACnBU,KAAK,KAAKZ,YAAY,IACtB,CAACJ,SAAS,IACV+B,iBAAiB,IACjBzB,uBACH;IACD+C,YAAY,EAAEhD,eAAgB;IAC9BiD,uBAAuB,EAAE3C,2BAA4B;IACrDV,QAAQ,EAAGsD,aAAa,IACpBzC,YAAY,CAAC;MAAEC,KAAK,EAAEwC,aAAa;MAAE5B,IAAI;MAAEI;IAAkB,CAAC,EAAEf,KAAK,CACxE;IACDjB,SAAS,EAAEA;EAAU,CACxB,CACJ,CAAC,EACD8C,uBAAuB,iBACpBzD,KAAA,CAAA0D,aAAA,CAACnD,oCAAoC,QAAC,oGAGA,CAErB,CAAC;AAElC,CAAC;AAED,eAAeE,oBAAoB","ignoreList":[]}
|
|
@@ -141,45 +141,73 @@ export const restoreSelection = element => {
|
|
|
141
141
|
selection.addRange(range);
|
|
142
142
|
range.collapse(true);
|
|
143
143
|
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
155
|
-
|
|
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
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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":[]}
|