{"version":3,"sources":["../src/SimpleMdeReact.tsx"],"sourcesContent":["import React, {\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from \"react\";\nimport SimpleMDE, { Options } from \"easymde\";\n\nimport type { Editor, EditorEventMap, KeyMap, Position } from \"codemirror\";\nimport { EditorChange } from \"codemirror\";\n\nlet _id = 0;\n\nconst generateId = () => `simplemde-editor-${++_id}`;\n\nexport type DOMEvent =\n  | \"mousedown\"\n  | \"dblclick\"\n  | \"touchstart\"\n  | \"contextmenu\"\n  | \"keydown\"\n  | \"keypress\"\n  | \"keyup\"\n  | \"cut\"\n  | \"copy\"\n  | \"paste\"\n  | \"dragstart\"\n  | \"dragenter\"\n  | \"dragover\"\n  | \"dragleave\"\n  | \"drop\";\n\nexport type CopyEvents = {\n  [TKey in string &\n    DOMEvent &\n    keyof DocumentAndElementEventHandlersEventMap as `${TKey}`]?: (\n    instance: Editor,\n    event: DocumentAndElementEventHandlersEventMap[TKey]\n  ) => void;\n};\n\nexport type GlobalEvents = {\n  [TKey in string &\n    DOMEvent &\n    keyof GlobalEventHandlersEventMap as `${TKey}`]?: (\n    instance: Editor,\n    event: GlobalEventHandlersEventMap[TKey]\n  ) => void;\n};\n\nexport type DefaultEvent = (instance: Editor, ...args: any[]) => void;\n\nexport type IndexEventsSignature = {\n  [key: string]: DefaultEvent | undefined;\n};\n\nexport interface SimpleMdeToCodemirrorEvents\n  extends CopyEvents,\n    GlobalEvents,\n    IndexEventsSignature,\n    Partial<EditorEventMap> {}\n\nexport type GetMdeInstance = (instance: SimpleMDE) => void;\nexport type GetCodemirrorInstance = (instance: Editor) => void;\nexport type GetLineAndCursor = (instance: Position) => void;\n\nexport interface SimpleMDEReactProps\n  extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n  id?: string;\n  onChange?: (value: string, changeObject?: EditorChange) => void;\n  value?: string;\n  extraKeys?: KeyMap;\n  options?: SimpleMDE.Options;\n  events?: SimpleMdeToCodemirrorEvents;\n  getMdeInstance?: GetMdeInstance;\n  getCodemirrorInstance?: GetCodemirrorInstance;\n  getLineAndCursor?: GetLineAndCursor;\n  placeholder?: string;\n  textareaProps?: Omit<\n    React.HTMLAttributes<HTMLTextAreaElement>,\n    \"id\" | \"style\" | \"placeholder\"\n  >;\n}\n\nconst useHandleEditorInstanceLifecycle = ({\n  options,\n  id,\n  currentValueRef,\n  textRef,\n}: {\n  options?: Options;\n  id: string;\n  currentValueRef: React.MutableRefObject<string | undefined>;\n  textRef: HTMLTextAreaElement | null;\n}) => {\n  const [editor, setEditor] = useState<SimpleMDE | null>(null);\n\n  const imageUploadCallback = useCallback(\n    (\n      file: File,\n      onSuccess: (url: string) => void,\n      onError: (error: string) => void\n    ) => {\n      const imageUpload = options?.imageUploadFunction;\n      if (imageUpload) {\n        const _onSuccess = (url: string) => {\n          onSuccess(url);\n        };\n        imageUpload(file, _onSuccess, onError);\n      }\n    },\n    [options?.imageUploadFunction]\n  );\n\n  const editorRef = useRef(editor);\n  editorRef.current = editor;\n\n  useEffect(() => {\n    let editor: SimpleMDE;\n    if (textRef) {\n      const initialOptions = {\n        element: textRef,\n        initialValue: currentValueRef.current,\n      };\n      const imageUploadFunction = options?.imageUploadFunction\n        ? imageUploadCallback\n        : undefined;\n      editor = new SimpleMDE(\n        Object.assign({}, initialOptions, options, {\n          imageUploadFunction,\n        })\n      );\n      setEditor(editor);\n    }\n    return () => {\n      editor?.toTextArea();\n      editor?.cleanup();\n    };\n  }, [textRef, currentValueRef, id, imageUploadCallback, options]);\n\n  const codemirror = useMemo(() => {\n    return editor?.codemirror;\n  }, [editor?.codemirror]) as Editor | undefined;\n  return { editor, codemirror };\n};\n\nexport const SimpleMdeReact = React.forwardRef<\n  HTMLDivElement,\n  SimpleMDEReactProps\n>((props, ref) => {\n  const {\n    events,\n    value,\n    options,\n    children,\n    extraKeys,\n    getLineAndCursor,\n    getMdeInstance,\n    getCodemirrorInstance,\n    onChange,\n    id: anId,\n    placeholder,\n    textareaProps,\n    ...rest\n  } = props;\n\n  const id = useMemo(() => anId ?? generateId(), [anId]);\n\n  const elementWrapperRef = useRef<HTMLDivElement | null>(null);\n  const nonEventChangeRef = useRef<boolean>(true);\n\n  // This is to not pass value as a dependency e.g. to keep event handlers referentially\n  // stable and do not `off` and `on` on each value change\n  // plus to avoid unnecessary EasyEde editor recreation on each value change while still, if it has to be remounted\n  // due to options and other deps change, to preserve that last value and not the default one from the first render.\n  const currentValueRef = useRef(value);\n  currentValueRef.current = value;\n\n  const [textRef, setTextRef] = useState<HTMLTextAreaElement | null>(null);\n  const { editor, codemirror } = useHandleEditorInstanceLifecycle({\n    options,\n    id,\n    currentValueRef,\n    textRef,\n  });\n\n  useEffect(() => {\n    // If change comes from the event we don't need to update `SimpleMDE` value as it already has it\n    // Otherwise we shall set it as it comes from `props` set from the outside. E.g. by some reset button and whatnot\n    if (nonEventChangeRef.current) {\n      editor?.value(value ?? \"\");\n    }\n    nonEventChangeRef.current = true;\n  }, [editor, value]); //  _: Editor | Event <===== is to please TS :)\n  const onCodemirrorChangeHandler = useCallback(\n    (_: Editor | Event, changeObject?: EditorChange) => {\n      if (editor?.value() !== currentValueRef.current) {\n        nonEventChangeRef.current = false;\n        onChange?.(editor?.value() ?? \"\", changeObject);\n      }\n    },\n    [editor, onChange]\n  );\n\n  useEffect(() => {\n    // For some reason it doesn't work out of the box, this makes sure it's working correctly\n    if (options?.autofocus) {\n      codemirror?.focus();\n      codemirror?.setCursor(codemirror?.lineCount(), 0);\n    }\n  }, [codemirror, options?.autofocus]);\n\n  const getCursorCallback = useCallback(() => {\n    // https://codemirror.net/doc/manual.html#api_selection\n    codemirror && getLineAndCursor?.(codemirror.getDoc().getCursor());\n  }, [codemirror, getLineAndCursor]);\n\n  useEffect(() => {\n    getCursorCallback();\n  }, [getCursorCallback]);\n\n  useEffect(() => {\n    editor && getMdeInstance?.(editor);\n  }, [editor, getMdeInstance]);\n\n  useEffect(() => {\n    codemirror && getCodemirrorInstance?.(codemirror);\n  }, [codemirror, getCodemirrorInstance, getMdeInstance]);\n\n  useEffect(() => {\n    // https://codemirror.net/doc/manual.html#option_extraKeys\n    if (extraKeys && codemirror) {\n      codemirror.setOption(\n        \"extraKeys\",\n        Object.assign({}, codemirror.getOption(\"extraKeys\"), extraKeys)\n      );\n    }\n  }, [codemirror, extraKeys]);\n\n  useEffect(() => {\n    const toolbarNode =\n      elementWrapperRef.current?.getElementsByClassName(\n        \"editor-toolbarNode\"\n      )[0];\n    const handler = codemirror && onCodemirrorChangeHandler;\n    if (handler) {\n      toolbarNode?.addEventListener(\"click\", handler);\n      return () => {\n        toolbarNode?.removeEventListener(\"click\", handler);\n      };\n    }\n    return () => {};\n  }, [codemirror, onCodemirrorChangeHandler]);\n\n  useEffect(() => {\n    codemirror?.on(\"change\", onCodemirrorChangeHandler);\n    codemirror?.on(\"cursorActivity\", getCursorCallback);\n    return () => {\n      codemirror?.off(\"change\", onCodemirrorChangeHandler);\n      codemirror?.off(\"cursorActivity\", getCursorCallback);\n    };\n  }, [codemirror, getCursorCallback, onCodemirrorChangeHandler]);\n\n  const prevEvents = useRef(events);\n\n  useEffect(() => {\n    const isNotFirstEffectRun = events !== prevEvents.current;\n    isNotFirstEffectRun &&\n      prevEvents.current &&\n      Object.entries(prevEvents.current).forEach(([event, handler]) => {\n        handler && codemirror?.off(event as keyof EditorEventMap, handler);\n      });\n\n    events &&\n      Object.entries(events).forEach(([event, handler]) => {\n        handler && codemirror?.on(event as keyof EditorEventMap, handler);\n      });\n    prevEvents.current = events;\n    return () => {\n      events &&\n        Object.entries(events).forEach(([event, handler]) => {\n          handler && codemirror?.off(event as keyof EditorEventMap, handler);\n        });\n    };\n  }, [codemirror, events]);\n\n  return (\n    <div\n      id={`${id}-wrapper`}\n      {...rest}\n      ref={(aRef) => {\n        if (typeof ref === \"function\") {\n          ref(aRef);\n        } else if (ref) {\n          ref.current = aRef;\n        }\n        elementWrapperRef.current = aRef;\n      }}\n    >\n      <textarea\n        {...textareaProps}\n        id={id}\n        placeholder={placeholder}\n        ref={setTextRef}\n        style={{ display: \"none\" }}\n      />\n    </div>\n  );\n});\n\nSimpleMdeReact.displayName = \"SimpleMdeReact\";\n\nexport default SimpleMdeReact;\n"],"mappings":"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","names":["editor"]}