diff --git a/package.json b/package.json index 963c4d4..473e20d 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "0.2.8", + "version": "0.2.9", "license": "MIT", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -95,4 +95,4 @@ "\\.(css|less|scss|sass)$": "identity-obj-proxy" } } -} +} \ No newline at end of file diff --git a/src/components/RaraEditor/RaraEditor.tsx b/src/components/RaraEditor/RaraEditor.tsx index e1821e4..93f74e2 100644 --- a/src/components/RaraEditor/RaraEditor.tsx +++ b/src/components/RaraEditor/RaraEditor.tsx @@ -74,13 +74,14 @@ const RaraEditor = (props: RaraEditorProps) => { mentionDetailRenderer, styles, value, - autoFocus=false, - + autoFocus = false, + toolbarIgnorList, + hideOnBlur = false } = props; - - const ref = React.useRef(null); + const ref = React.useRef(null); + const [blur, setBlur] = React.useState(!autoFocus) const [target, setTarget] = React.useState(); const [index, setIndex] = React.useState(0); const [search] = React.useState(''); @@ -99,7 +100,8 @@ const RaraEditor = (props: RaraEditorProps) => { ), [] ); - + + const { onDOMBeforeInput, onKeyDown, @@ -146,9 +148,16 @@ const RaraEditor = (props: RaraEditorProps) => { ] ); const renderLeaf = React.useCallback( - (props: RenderLeafProps) => , + (props: RenderLeafProps) => , [] ); + React.useEffect(() => { + if(!autoFocus && !hideOnBlur){ + + setBlur(false) + } + + },[autoFocus]) React.useEffect(() => { if (target && searchResults.length > 0) { @@ -169,9 +178,10 @@ const RaraEditor = (props: RaraEditorProps) => { style={styles} > { - + //TO check if the values are changed or not const isAstChange = editor.operations.some( op => 'set_selection' !== op.type @@ -234,19 +244,20 @@ const RaraEditor = (props: RaraEditorProps) => { return; } } + setTarget(null); if (isAstChange) { // Save the value to Local Storage. setFinalData(change as unknown as string); - if(JSON.stringify(change) === '[{"type":"paragraph","children":[{"text":""}]}]') - { onChange && onChange(''); - } else { + if (JSON.stringify(change) === '[{"type":"paragraph","children":[{"text":""}]}]') { + onChange && onChange(''); + } else { onChange && onChange(JSON.stringify(change)); } //managing mention data const edtr = editor.operations; - + const mentionUser = edtr.find( (e: BaseOperation): e is BaseInsertNodeOperation => e.type === 'insert_node' && e?.node?.type === 'mention' @@ -254,7 +265,7 @@ const RaraEditor = (props: RaraEditorProps) => { const removeMentionUser = edtr.filter( (e: BaseOperation): e is RemoveNodeOperation => - e.type === 'remove_node' && (e?.node?.type === 'mention' ||(e?.node?.type === 'mention' && e?.node?.text === "")), + e.type === 'remove_node' && (e?.node?.type === 'mention' || (e?.node?.type === 'mention' && e?.node?.text === "")), ); const mentionContact = edtr.find( (e: BaseOperation): e is BaseInsertNodeOperation => @@ -272,32 +283,31 @@ const RaraEditor = (props: RaraEditorProps) => { // console.log({editor,edtr}); let last let newLast - const setSelection = edtr.filter((e:BaseOperation):e is SelectionOperation => e.type === 'set_selection') - - for(let i=0; i e.type === 'set_selection') + + for (let i = 0; i < removeMentionUser.length; i++) { setMentionUsers((pre: string[]) => [ ...removeById(pre, removeMentionUser[i].node.id!), ]); } - - last = removeMentionUser[0].path[removeMentionUser[0].path.length -1] - 1 , - newLast = [...removeMentionUser[0].path], - newLast[removeMentionUser[0].path.length - 1] = last, - Transforms.select(editor, { - anchor: Editor.end(editor, { - path: setSelection ? setSelection[0]?.newProperties?.anchor ?setSelection[0]?.newProperties?.anchor.path :setSelection[0]?.newProperties?.focus?.path! : [...newLast], - offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 - }), - - focus: Editor.end(editor, { - path: setSelection ? setSelection[0]?.newProperties?.anchor ?setSelection[0]?.newProperties?.anchor.path :setSelection[0]?.newProperties?.focus?.path! : [...newLast], - - - offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 - }) - }); - + + last = removeMentionUser[0].path[removeMentionUser[0].path.length - 1] - 1, + newLast = [...removeMentionUser[0].path], + newLast[removeMentionUser[0].path.length - 1] = last, + Transforms.select(editor, { + anchor: Editor.end(editor, { + path: setSelection ? setSelection[0]?.newProperties?.anchor ? setSelection[0]?.newProperties?.anchor.path : setSelection[0]?.newProperties?.focus?.path! : [...newLast], + offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 + }), + + focus: Editor.end(editor, { + path: setSelection ? setSelection[0]?.newProperties?.anchor ? setSelection[0]?.newProperties?.anchor.path : setSelection[0]?.newProperties?.focus?.path! : [...newLast], + + + offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 + }) + }); + } if (mentionContact) { setMentionContacts((pre: any) => [ @@ -307,46 +317,60 @@ const RaraEditor = (props: RaraEditorProps) => { } if (removeMentionContact.length > 0) { - + let last let newLast - for(let i=0; i [ ...removeById(pre, removeMentionContact[i].node.id!), - + ]); } - last = removeMentionContact[0].path[removeMentionContact[0].path.length -1] - 1, - newLast = [...removeMentionContact[0].path], - newLast[removeMentionContact[0].path.length - 1] = last, - Transforms.select(editor, { - anchor: Editor.end(editor, { - path: [...newLast], - offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 - - }), - - focus: Editor.end(editor, { - path: [...newLast], - offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 - - }) - }); + last = removeMentionContact[0].path[removeMentionContact[0].path.length - 1] - 1, + newLast = [...removeMentionContact[0].path], + newLast[removeMentionContact[0].path.length - 1] = last, + Transforms.select(editor, { + anchor: Editor.end(editor, { + path: [...newLast], + offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 + + }), + + focus: Editor.end(editor, { + path: [...newLast], + offset: edtr[0].type === "remove_text" ? edtr[0].offset : 0 + + }) + }); } } }} editor={editor} value={finalData as Descendant[]} > - {!readOnly && ( + {(!readOnly && !toolbarIgnorList?.includes('all') && !blur ) && (
- +
)} { + if(hideOnBlur) { + + setBlur(false) + } + }} + onBlur={() => { + if(hideOnBlur) + { + + setBlur(true) + } + + }} autoFocus={autoFocus} renderElement={(p: RenderElementProps) => { return renderElement(p); diff --git a/src/components/RaraEditor/styles.css b/src/components/RaraEditor/styles.css index fd541eb..6d2a5e4 100644 --- a/src/components/RaraEditor/styles.css +++ b/src/components/RaraEditor/styles.css @@ -8,7 +8,7 @@ padding: 12px; border-radius: 4px; width: auto; - min-height: 60px; + min-height: auto; } .rte-editor.read-only { diff --git a/src/components/Toolbar/Toolbar.tsx b/src/components/Toolbar/Toolbar.tsx index 0d41dbf..1663e5c 100644 --- a/src/components/Toolbar/Toolbar.tsx +++ b/src/components/Toolbar/Toolbar.tsx @@ -15,22 +15,27 @@ import { Headings } from './Headings'; import { ListsMarkers } from './Lists'; import { MarkerItem, Markers } from './Markers'; import { TextAlignMarkers } from './TextAlignMarkers'; +import { ElementIgnorType } from '../../types'; // interface ToolbarProps { // items: any[]; // onSearch?: (e: string) => void; // } -export const Toolbar = () => { +export const Toolbar = ({ ignorList }: { ignorList?: ElementIgnorType[] }) => { const editor = useSlate(); // console.log(editor); return (
- - + {!ignorList?.includes('color') && + <> + + + } + - { }} active={isBlockActive(editor, 'block-quote')} /> - - - - - - - + } + {!ignorList?.includes('heading') && <> + + } + {!ignorList?.includes('alignMarker') && } + {!ignorList?.includes('listMarker') && <> + + } + {!ignorList?.includes('code') && <> { toggleBlock(editor, 'code'); }} /> - - + } + {!ignorList?.includes('check-list-item') && <> { toggleBlock(editor, 'check-list-item'); }} /> - - + } + {ignorList?.includes('link') && <> { } }} /> - + + } {/* */}
-
+ ); }; diff --git a/src/types/index.ts b/src/types/index.ts index f66043e..d04c77d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -10,8 +10,8 @@ export type ParagraphElement = { align?: string; color?: string; children: CustomTextElement[]; - id?:string|number - text?:string + id?: string | number + text?: string }; export type CustomTextElement = { text?: string; @@ -21,27 +21,27 @@ export type CustomTextElement = { underline?: boolean; type?: string; children?: any[]; - id?:string|number; - code?:boolean; - color?:string; - highlight?:boolean - editor?:RaraEditorType + id?: string | number; + code?: boolean; + color?: string; + highlight?: boolean + editor?: RaraEditorType }; export type CodeElement = { align?: string; type?: 'code'; children?: CustomTextElement[]; - id?:string|number - text?:string + id?: string | number + text?: string }; export type BlockQuoteElement = { align?: string; type?: 'block-quote' | string; children?: CustomTextElement[]; - id?:string|number - text?:string + id?: string | number + text?: string }; export type CustomElement = | BlockQuoteElement @@ -67,14 +67,27 @@ export type ElementType = | 'link' | 'mention' | undefined; +export type ElementIgnorType = + | 'color' + | 'block-quote' + | 'code' + | 'heading' + | 'alignMarker' + | 'listMarker' + | 'check-list-item' + | 'paragraph' + | 'link' + | 'mention' + | 'all' + | undefined; export type ColoredElement = { align?: string; type: 'color'; color?: string; children: any[]; - id?:string|number - text?:string + id?: string | number + text?: string }; export type ChecklistElement = { @@ -82,26 +95,26 @@ export type ChecklistElement = { type: 'check-list-item'; checked: boolean; children: CustomTextElement[]; - id?:string|number - text?:string + id?: string | number + text?: string }; export type HeadingElement = { align?: string; type?: - | 'heading-one' - | 'heading-two' - | 'heading-three' - | 'heading-four' - | 'heading-five' - | 'heading-six' - | 'bulleted-list' - | 'list-item' - | 'numbered-list' - | 'mentionContact'; + | 'heading-one' + | 'heading-two' + | 'heading-three' + | 'heading-four' + | 'heading-five' + | 'heading-six' + | 'bulleted-list' + | 'list-item' + | 'numbered-list' + | 'mentionContact'; children: CustomTextElement[]; - id?:string|number - text?:string + id?: string | number + text?: string }; @@ -112,7 +125,7 @@ export type MentionElement = { label: string; metaData?: Record; children: CustomTextElement[]; - text?:string + text?: string }; @@ -121,8 +134,8 @@ export type LinkElement = { type: 'link'; url?: string; children: CustomTextElement[]; - id?:string|number - text?:string + id?: string | number + text?: string }; @@ -134,6 +147,7 @@ export type RaraEditorProps = { onCheckboxChange?: (checked: boolean, value: string) => void; onMentionListChange?: (mentionedItems: MentionItemProps[]) => void; // onMentionQuery?: (query: string) => Promise; + toolbarIgnorList?: ElementIgnorType[] onMentionQuery?: MentionItemProps[]; onMentionContactQuery?: MentionItemProps[]; isMentionLoading?: boolean; @@ -152,7 +166,8 @@ export type RaraEditorProps = { styles?: React.CSSProperties; onMentionContact?: (e: number[]) => void; onMentionUser?: (e: string[]) => void; - autoFocus?:boolean + autoFocus?: boolean + hideOnBlur?:boolean }; export type MentionItemProps = { @@ -163,10 +178,11 @@ export type MentionItemProps = { declare module 'slate' { interface BaseEditor { - type?:string; - id?:string - text?:string - }} + type?: string; + id?: string + text?: string + } +} @@ -180,11 +196,11 @@ export interface IediterHooks { target: Location | BaseRange | null | undefined; searchResults: MentionItemProps[]; setIndex: (e: number) => void; - insertMention: (editor: RaraEditorType, item: MentionItemProps,target:BaseRange) => void; + insertMention: (editor: RaraEditorType, item: MentionItemProps, target: BaseRange) => void; insertMentionContact: ( editor: RaraEditorType, item: MentionItemProps, - target:BaseRange + target: BaseRange ) => void; setTarget: Dispatch>; setSearchResults: Dispatch>; @@ -194,6 +210,6 @@ export interface IediterHooks { mentionIndicator: string | null; onMentionContact?: (e: number[]) => void; onMentionUser?: (e: string[]) => void; - + }