You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is there, anyone having the same issue of not rendering the mentioned list as when we use a static array to run and check the list... It is working fine but when we are fetching data from APIs and then trying to add it to the mentioned list, it is not working.
My Component file:
import { useState, useMemo, useRef, useEffect } from 'react'
import ReactQuill from 'react-quill'
import Quill from 'quill'
import Toolbar from './Toolbar/Toolbar'
import 'react-quill/dist/quill.snow.css'
import MentionFormat from './Formats/mention'
import MentionModule from './Modules/mention'
import { FORMATS } from './Utils'
import './mention.css'
// import './Modules/floating-label.scss'
import { createPortal } from 'react-dom'
import MentionsList from './MentionList'
import { Typography } from '@mui/material'
Quill.register({ 'formats/mention': MentionFormat })
Quill.register('modules/mention', MentionModule)
const Size = Quill.import('formats/size')
Size.whitelist = ['extra-small', 'small', 'medium', 'large']
Quill.register(Size, true)
let Font = Quill.import('formats/font')
Font.whitelist = ['inconsolata', 'roboto', 'mirza', 'arial']
Quill.register(Font, true)
// Props to fetch data
export type EditorProps = {
hideImageButton?: boolean
hideToolBar?: boolean
defaultVal?: string
setupMentionValues: IMentionItems[]
height?: string
width?: string
label?: string
readOnly?: boolean
getValueString?: (selectedItem: string) => void
getValue?: (selectedItem: string) => void
getMentionItem?: (selectedItem: IMentionValue) => void
getHTMLContent?: (selectedItem: string) => void
}
// Interface for setup mention items
export interface IMentionItems {
id: string
value: string
}
// Interface for get mention values
export interface IMentionValue {
name: string
id: string
}
const QUILL_FORAMTS = FORMATS.map(({ name }) => name)
export default function IvpSummernote(props: EditorProps) {
// Properties
const {
setupMentionValues,
defaultVal,
hideImageButton,
hideToolBar,
getValueString,
getValue,
getMentionItem,
getHTMLContent,
height,
width,
label,
readOnly
} = props
const text = `${defaultVal}`
const [open, setOpen] = useState(false)
const [mentions, setMentions] = useState([])
const [isFocused, setIsFocused] = useState(false)
const [hasContent, setHasContent] = useState(text && text.trim().length > 0)
const quillContainerRef = useRef(null)
const ref = useRef<any>()
// Mention View Open and Close
/* istanbul ignore next */
const handleClose = () => {
setOpen(false)
}
/* istanbul ignore next */
const handleOpen = () => {
setOpen(true)
}
// Mention Item Click
/* istanbul ignore next */
const onItemClick = ({ data }) => {
if (getMentionItem) getMentionItem(data)
let nm = data.name
data.name = `{${nm}}`
ref.current.editor.emitter.emit('mention-clicked', data)
handleClose()
}
// Undo and redo functions for Custom Toolbar
/* istanbul ignore next */
function undoChange(this: {
quill: any
undo: () => void
redo: () => void
}) {
this.quill.history.undo()
}
/* istanbul ignore next */
function redoChange(this: {
quill: any
undo: (this: { quill: any; undo: () => void; redo: () => void }) => void
redo: () => void
}) {
this.quill.history.redo()
}
// Handle Changes when user type in text Editor
/* istanbul ignore next */
const handleChangeSelection = () => {
let txt = ref.current.editor.container.innerText
let justHtml = ref.current.editor.root.innerHTML
const replacedText = txt?.replace(/@\{([^}]+)\}/g, (match, p1) => {
const foundItem = setupMentionValues.find((item) => item.value === p1)
return foundItem ? foundItem.id : match
})
setHasContent(txt && txt?.trim().length > 0)
if (getValueString) getValueString(txt)
if (getValue) getValue(replacedText)
if (getHTMLContent) getHTMLContent(justHtml)
}
const handleFocus = () => {
setIsFocused(true)
}
const handleBlur = () => {
setIsFocused(false)
}
// const handleChange = (content) => {
// ref.current.onChange(content)
// setHasContent(content && content.trim().length > 0)
// }
/* istanbul ignore next */
const mentionCallBacks = () => {
const selection = ref.current.editor.getSelection(true)
ref.current.editor.insertText(selection.index, '@')
ref.current.editor.blur()
ref.current.editor.focus()
}
// Render Mention List
/* istanbul ignore next */
const renderMentionList = ({ quillContainer, searchTerm }) => {
let matches: any = []
if (searchTerm.length === 0) {
matches = setupMentionValues
} else {
for (let i = 0; i < setupMentionValues.length; i++) {
if (
setupMentionValues[i].value
.toLowerCase()
.indexOf(searchTerm.toLowerCase()) >= 0
)
matches.push(setupMentionValues[i])
}
}
if (!quillContainerRef.current) {
quillContainerRef.current = quillContainer
}
setMentions(matches)
setOpen(true)
}
// Assuming you have a reference to your text editor element
// Get the selection object
const selection = window.getSelection()
let topValue = 0
let leftValue = 0
/* istanbul ignore next */
if (selection && selection.rangeCount > 0) {
// Get the first range in the selection
const range = selection.getRangeAt(0)
// Get the bounding client rect of the range
const rect = range.getBoundingClientRect()
// Calculate the position relative to the text editor
const top = rect.top + window.scrollY
const left = rect.left + window.scrollX
topValue = top
leftValue = left
}
// const labelStyle: React.CSSProperties = {
// // position: 'absolute',
// top: '-150px',
// left: '80px',
// // transform: 'translateY(-50%)',
// // transition: 'all 0.3s ease',
// // pointerEvents: 'none' as React.CSSProperties['pointerEvents'], // Set the pointerEvents property correctly
// color: '#9e9e9e'
// // Optional: Add styles for active state
// // ...(active && {
// // color: 'blue', // Change color if active
// // fontSize: '12px', // Adjust size if active
// // }),
// }
// const labelStyle2: React.CSSProperties = {
// position: 'absolute',
// transition: 'all 0.3s ease',
// top: isFocused || hasContent ? '-50px' : '',
// fontSize: isFocused || hasContent ? '12px' : 'inherit',
// color: isFocused || hasContent ? '#3f51b5' : '#9e9e9e'
// // transform: isFocused || hasContent ? 'translateY(-50%)' : ''
// }
// UseEffect
useEffect(() => {
handleChangeSelection()
})
return (
<>
{useMemo(
() => (
<>
{/* <Typography sx={{ top: '-140px', width: '6rem' }}>
{label}
</Typography> */}
<ReactQuill
style={{
height: height ? height : '15em',
width: width ? width : '15em',
borderRadius: '5px',
border: 'solid 1px red',
maxHeight: '40em',
minWidth: '20em',
maxWidth: '90em'
}}
ref={ref}
id='text-Editor'
modules={{
clipboard: {
matchVisual: true
},
toolbar: hideToolBar
? false
: {
container: '#toolbar',
size: ['12px', '16px', '24px', '36px'],
handlers: {
undo: undoChange,
redo: redoChange,
mention: mentionCallBacks
}
},
history: {
delay: 500,
maxStack: 100,
userOnly: true
},
mention: {
allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
mentionDenotationChars: ['@'],
positioningStrategy: 'inside-quill',
hideMentionList: handleClose,
showMnetionList: handleOpen,
renderMentionList: renderMentionList
}
}}
formats={QUILL_FORAMTS}
theme='snow'
defaultValue={text}
readOnly={readOnly}
onChangeSelection={handleChangeSelection}
// onChange={handleChange}
onFocus={handleFocus}
onBlur={handleBlur}
placeholder='WhereClause'
/>
</>
),
/* eslint-disable react-hooks/exhaustive-deps */
[]
/* eslint-enable react-hooks/exhaustive-deps */
)}
{hideToolBar ? null : (
<Toolbar width={width ? width : '20em'} hideImgBtn={hideImageButton} />
)}
<p id='counter'></p>
{quillContainerRef.current &&
/* istanbul ignore next */
createPortal(
<MentionsList
open={open}
items={mentions}
top={topValue}
left={leftValue}
oneClose={handleClose}
onItemClick={onItemClick}
/>,
quillContainerRef.current
)}
</>
)
}
Hey Techies,
Is there, anyone having the same issue of not rendering the mentioned list as when we use a static array to run and check the list... It is working fine but when we are fetching data from APIs and then trying to add it to the mentioned list, it is not working.
My Component file:
My Rendering Component file:
The text was updated successfully, but these errors were encountered: