-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
373 - Use ReactQuill and QuillMention instead of react-mentions
- Loading branch information
1 parent
14e201e
commit cc109da
Showing
17 changed files
with
694 additions
and
281 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import {Quill} from 'react-quill'; | ||
|
||
const Embed = Quill.import('blots/embed'); | ||
|
||
export default class MentionBlot extends Embed { | ||
static blotName = 'bytechef-mention'; | ||
static tagName = 'div'; | ||
static className = 'bytechef-mention'; | ||
|
||
static create(data: {denotationChar: string; value: string; icon: string}) { | ||
const node = super.create(); | ||
const iconNode = document.createElement('span'); | ||
const contentNode = document.createElement('span'); | ||
|
||
iconNode.innerHTML = data.icon; | ||
contentNode.innerHTML = data.value; | ||
|
||
node.appendChild(iconNode); | ||
node.appendChild(contentNode); | ||
|
||
return MentionBlot.setDataValues(node, data); | ||
} | ||
|
||
static setDataValues(element: HTMLElement, data: {[key: string]: string}) { | ||
const domNode = element; | ||
|
||
Object.keys(data).forEach((key) => { | ||
domNode.dataset[key] = data[key]; | ||
|
||
if (key === 'component') { | ||
domNode.dataset[key] = JSON.stringify(data[key]); | ||
} | ||
}); | ||
|
||
return domNode; | ||
} | ||
|
||
static value(domNode: {dataset: object}) { | ||
return domNode.dataset; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import QuillMention from 'quill-mention'; | ||
import React, {useCallback, useRef, useState} from 'react'; | ||
import ReactQuill, {Quill} from 'react-quill'; | ||
|
||
import './mentionsInput.css'; | ||
|
||
import {useNodeDetailsDialogStore} from '@/pages/automation/project/stores/useNodeDetailsDialogStore'; | ||
import {DataPillType} from '@/types/types'; | ||
import {twMerge} from 'tailwind-merge'; | ||
|
||
import MentionBlot from './MentionBlot'; | ||
|
||
Quill.register('modules/mentions', QuillMention); | ||
Quill.register('formats/bytechef-mention', MentionBlot); | ||
|
||
const MentionInputListItem = (item: DataPillType) => ` | ||
<div> | ||
<span>${item.icon}</span> | ||
<span>${item.value}</span> | ||
</div> | ||
`; | ||
|
||
type MentionsInputProps = { | ||
data: Array<DataPillType>; | ||
id: string; | ||
placeholder?: string; | ||
}; | ||
|
||
const MentionsInput = ({data, id, placeholder}: MentionsInputProps) => { | ||
const [value, setValue] = useState(''); | ||
const editorRef = useRef<ReactQuill>(null); | ||
|
||
const {focusedInput, setFocusedInput} = useNodeDetailsDialogStore(); | ||
|
||
const modules = { | ||
mention: { | ||
allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/, | ||
blotName: 'mention', | ||
dataAttributes: ['component'], | ||
fixMentionsToQuill: true, | ||
mentionDenotationChars: ['${'], | ||
onSelect: useCallback( | ||
( | ||
item: DataPillType, | ||
insertItem: ( | ||
data: DataPillType, | ||
programmaticInsert: boolean, | ||
overriddenOptions: object | ||
) => void | ||
) => { | ||
const component = JSON.parse(item.component as string); | ||
|
||
insertItem( | ||
{ | ||
component, | ||
icon: component.icon, | ||
id: item.id, | ||
value: item.value, | ||
}, | ||
false, | ||
{ | ||
blotName: 'bytechef-mention', | ||
} | ||
); | ||
}, | ||
[] | ||
), | ||
renderItem: useCallback( | ||
(item: DataPillType) => MentionInputListItem(item), | ||
[] | ||
), | ||
showDenotationChar: false, | ||
source: useCallback( | ||
( | ||
searchTerm: string, | ||
renderList: (arg1: Array<object>, arg2: string) => void | ||
) => { | ||
const formattedData = data.map((datum) => ({ | ||
...datum, | ||
icon: JSON.parse(datum.component as string).icon, | ||
})); | ||
|
||
if (searchTerm.length === 0) { | ||
renderList(formattedData, searchTerm); | ||
} else { | ||
const matches = formattedData.filter( | ||
(datum) => | ||
~datum.value | ||
.toLowerCase() | ||
.indexOf(searchTerm.toLowerCase()) | ||
); | ||
|
||
renderList(matches, searchTerm); | ||
} | ||
}, | ||
[data] | ||
), | ||
spaceAfterInsert: true, | ||
}, | ||
toolbar: false, | ||
}; | ||
|
||
return ( | ||
<ReactQuill | ||
className={twMerge( | ||
'h-full w-full', | ||
focusedInput?.props.id === id && 'focused' | ||
)} | ||
formats={['bytechef-mention', 'mention']} | ||
id={id} | ||
key="keyBAR" | ||
modules={modules} | ||
onChange={setValue} | ||
onFocus={() => { | ||
if (editorRef.current) { | ||
setFocusedInput(editorRef.current); | ||
} | ||
}} | ||
placeholder={placeholder} | ||
ref={editorRef} | ||
value={value} | ||
/> | ||
); | ||
}; | ||
|
||
export default React.memo(MentionsInput); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
declare module 'quill-mention'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
.quill.focused .ql-editor { | ||
@apply shadow-lg shadow-blue-200; | ||
@apply ring ring-blue-500; | ||
} | ||
|
||
.ql-editor.ql-blank::before { | ||
@apply content-[attr(data-placeholder)]; | ||
@apply absolute; | ||
@apply pointer-events-none; | ||
@apply opacity-100; | ||
@apply text-gray-400; | ||
} | ||
|
||
.ql-clipboard { | ||
@apply invisible; | ||
@apply h-0; | ||
} | ||
|
||
.ql-editor { | ||
@apply border; | ||
@apply rounded-md; | ||
@apply p-2; | ||
@apply text-sm; | ||
@apply leading-8; | ||
@apply focus:outline-none focus:ring focus:ring-blue-500; | ||
} | ||
|
||
.ql-mention-list-container { | ||
@apply bg-gray-100; | ||
@apply border; | ||
@apply shadow-lg; | ||
@apply z-50; | ||
@apply m-4 mt-6; | ||
@apply rounded-md; | ||
@apply max-h-96; | ||
@apply overflow-y-auto; | ||
} | ||
|
||
.ql-mention-list { | ||
@apply rounded-md; | ||
@apply space-y-2; | ||
@apply p-2; | ||
} | ||
|
||
.ql-mention-list-item { | ||
@apply px-2 py-1; | ||
@apply text-sm; | ||
@apply bg-white; | ||
@apply rounded-md; | ||
@apply cursor-pointer; | ||
@apply border-2 border-transparent; | ||
@apply hover:border-2 hover:border-gray-400; | ||
@apply flex; | ||
} | ||
|
||
.ql-mention-list-item div { | ||
@apply flex; | ||
@apply items-center; | ||
@apply space-x-2; | ||
} | ||
|
||
.ql-mention-list-item svg { | ||
@apply h-4; | ||
@apply w-4; | ||
} | ||
|
||
.mention { | ||
@apply border; | ||
@apply bg-gray-100; | ||
@apply px-2 py-1; | ||
@apply rounded-full; | ||
} | ||
|
||
.mention::before { | ||
@apply bg-[url(data-icon)]; | ||
@apply content-['']; | ||
@apply h-4 w-4; | ||
} | ||
|
||
.bytechef-mention { | ||
@apply inline-flex; | ||
@apply items-center; | ||
} | ||
|
||
.bytechef-mention > span { | ||
@apply inline-flex; | ||
@apply items-center; | ||
@apply border; | ||
@apply bg-gray-100; | ||
@apply px-2; | ||
@apply rounded-full; | ||
} | ||
|
||
.bytechef-mention svg { | ||
@apply mr-1; | ||
@apply h-4 w-4; | ||
} |
Oops, something went wrong.