Skip to content

Commit

Permalink
feat: make image upload optional, support disable image resizing
Browse files Browse the repository at this point in the history
  • Loading branch information
petyosi committed Aug 18, 2023
1 parent 0518312 commit 823d1d3
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 39 deletions.
9 changes: 1 addition & 8 deletions src/examples/basics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,7 @@ export function MarkdownShortcuts() {
<MDXEditor
onChange={console.log}
markdown={helloMarkdown}
plugins={[
codeBlockPlugin({ codeBlockEditorDescriptors: [PlainTextCodeEditorDescriptor] }),
headingsPlugin(),
listsPlugin(),
linkPlugin(),
quotePlugin(),
markdownShortcutPlugin()
]}
plugins={[headingsPlugin(), listsPlugin(), linkPlugin(), quotePlugin(), markdownShortcutPlugin()]}
/>
)
}
4 changes: 2 additions & 2 deletions src/examples/images.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function HtmlImage() {
<MDXEditor
markdown={markdownWithHtmlImages}
plugins={[
imagePlugin(),
imagePlugin({ imageUploadHandler: async () => Promise.resolve('https://picsum.photos/200/300') }),
diffSourcePlugin(),
toolbarPlugin({ toolbarContents: () => <DiffSourceToggleWrapper>:)</DiffSourceToggleWrapper> })
]}
Expand All @@ -39,7 +39,7 @@ export function JsxImage() {
<MDXEditor
markdown={markdownWithHtmlImages}
plugins={[
imagePlugin(),
imagePlugin({ disableImageResize: true }),
diffSourcePlugin(),
jsxPlugin(),
toolbarPlugin({ toolbarContents: () => <DiffSourceToggleWrapper>:)</DiffSourceToggleWrapper> })
Expand Down
4 changes: 3 additions & 1 deletion src/plugins/image/ImageEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import styles from '../../styles/ui.module.css'
import classNames from 'classnames'
import { $isImageNode } from './ImageNode'
import ImageResizer from './ImageResizer'
import { imagePluginHooks } from '.'

export interface ImageEditorProps {
nodeKey: string
Expand Down Expand Up @@ -74,6 +75,7 @@ export function ImageEditor({ src, title, nodeKey, width, height }: ImageEditorP
const [selection, setSelection] = React.useState<RangeSelection | NodeSelection | GridSelection | null>(null)
const activeEditorRef = React.useRef<LexicalEditor | null>(null)
const [isResizing, setIsResizing] = React.useState<boolean>(false)
const [disableImageResize] = imagePluginHooks.useEmitterValues('disableImageResize')

const onDelete = React.useCallback(
(payload: KeyboardEvent) => {
Expand Down Expand Up @@ -221,7 +223,7 @@ export function ImageEditor({ src, title, nodeKey, width, height }: ImageEditorP
imageRef={imageRef}
/>
</div>
{draggable && isFocused && (
{draggable && isFocused && !disableImageResize && (
<ImageResizer editor={editor} imageRef={imageRef} onResizeStart={onResizeStart} onResizeEnd={onResizeEnd} />
)}
</div>
Expand Down
62 changes: 34 additions & 28 deletions src/plugins/image/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ import { CAN_USE_DOM } from '../../utils/detectMac'

export * from './ImageNode'

export type ImageUploadHandler = ((image: File) => Promise<string>) | null

/** @internal */
export const imageSystem = system(
(r, [{ rootEditor }]) => {
const insertImage = r.node<string>()
const imageAutocompleteSuggestions = r.node<string[]>([])

const imageUploadHandler = r.node<(image: File) => Promise<string>>((_) => {
throw new Error('Image upload handling is not implemented')
})
const disableImageResize = r.node<boolean>(false)
const imageUploadHandler = r.node<ImageUploadHandler>(null)

r.sub(r.pipe(insertImage, r.o.withLatestFrom(rootEditor)), ([src, theEditor]) => {
theEditor?.update(() => {
Expand All @@ -62,6 +62,9 @@ export const imageSystem = system(
},
COMMAND_PRIORITY_EDITOR
)

const theUploadHandler = r.getValue(imageUploadHandler)

editor?.registerCommand<DragEvent>(
DRAGSTART_COMMAND,
(event) => {
Expand All @@ -85,6 +88,10 @@ export const imageSystem = system(
COMMAND_PRIORITY_HIGH
)

if (theUploadHandler === null) {
return
}

editor?.registerCommand(
PASTE_COMMAND,
(event: ClipboardEvent) => {
Expand All @@ -95,7 +102,7 @@ export const imageSystem = system(
return false
} // If no image was present in the collection, bail.

const imageUploadHandlerValue = r.getValue(imageUploadHandler)
const imageUploadHandlerValue = r.getValue(imageUploadHandler)!

Promise.all(cbPayload.map((file) => imageUploadHandlerValue(file.getAsFile()!)))
.then((urls) => {
Expand All @@ -115,21 +122,17 @@ export const imageSystem = system(
return {
imageUploadHandler,
imageAutocompleteSuggestions,
disableImageResize,
insertImage
}
},
[coreSystem]
)

interface ImagePluginParams {
imageUploadHandler: (image: File) => Promise<string>
imageUploadHandler?: ImageUploadHandler
imageAutocompleteSuggestions?: string[]
}

const defaultParams: ImagePluginParams = {
imageUploadHandler: () => {
throw new Error('Image upload handling is not implemented')
}
disableImageResize?: boolean
}

export const [
Expand All @@ -141,9 +144,10 @@ export const [
id: 'image',
systemSpec: imageSystem,

applyParamsToSystem: (realm, params: ImagePluginParams = defaultParams) => {
realm.pubKey('imageUploadHandler', params.imageUploadHandler)
realm.pubKey('imageAutocompleteSuggestions', params.imageAutocompleteSuggestions || [])
applyParamsToSystem: (realm, params: ImagePluginParams) => {
realm.pubKey('imageUploadHandler', params?.imageUploadHandler || null)
realm.pubKey('imageAutocompleteSuggestions', params?.imageAutocompleteSuggestions || [])
realm.pubKey('disableImageResize', Boolean(params?.disableImageResize))
},

init: (realm) => {
Expand Down Expand Up @@ -218,26 +222,28 @@ function onDragover(event: DragEvent): boolean {
return true
}

function onDrop(event: DragEvent, editor: LexicalEditor, imageUploadHandler: (file: File) => Promise<string>): boolean {
function onDrop(event: DragEvent, editor: LexicalEditor, imageUploadHandler: ImageUploadHandler): boolean {
let cbPayload = Array.from(event.dataTransfer?.items || [])
cbPayload = cbPayload.filter((i) => /image/.test(i.type)) // Strip out the non-image bits

if (cbPayload.length > 0) {
event.preventDefault()
Promise.all(cbPayload.map((image) => imageUploadHandler(image.getAsFile()!)))
.then((urls) => {
urls.forEach((url) => {
editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
src: url,
altText: ''
if (imageUploadHandler !== null) {
event.preventDefault()
Promise.all(cbPayload.map((image) => imageUploadHandler(image.getAsFile()!)))
.then((urls) => {
urls.forEach((url) => {
editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
src: url,
altText: ''
})
})
})
})
.catch((e) => {
throw e
})
.catch((e) => {
throw e
})

return true
return true
}
}

const node = getImageNodeInSelection()
Expand Down

0 comments on commit 823d1d3

Please sign in to comment.