index.tsx
TLDR
This file contains a component called "Image" that represents an image block in a blocks editor. It includes two sub-components: "Display" and "Input" which handle the rendering and user input for the image block respectively.
Classes
Image
The Image component represents an image block in a blocks editor. It has the following properties:
-
name
: The name of the component ("image"). -
displayName
: The display name of the component ("Image"). -
slashCommand
: The slash command associated with the component ("/image"). -
prefix
: The prefix associated with the component (empty string). -
runSlashCommand
: A function that handles the execution of the slash command. -
editable
: A boolean indicating whether the component is editable. -
Display
: A sub-component that renders the image block. -
Input
: A sub-component that handles user input for the image block.
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useRef, useEffect, useState} from 'react'
import {BlockInputProps, ContentType} from '../types'
import octoClient from '../../../../octoClient'
import './image.scss'
type FileInfo = {
file: string|File
width?: number
align?: 'left'|'center'|'right'
}
const Image: ContentType<FileInfo> = {
name: 'image',
displayName: 'Image',
slashCommand: '/image',
prefix: '',
runSlashCommand: (): void => {},
editable: false,
Display: (props: BlockInputProps<FileInfo>) => {
const [imageDataUrl, setImageDataUrl] = useState<string|null>(null)
useEffect(() => {
if (!imageDataUrl) {
const loadImage = async () => {
if (props.value && props.value.file && typeof props.value.file === 'string') {
const fileURL = await octoClient.getFileAsDataUrl(props.currentBoardId || '', props.value.file)
setImageDataUrl(fileURL.url || '')
}
}
loadImage()
}
}, [props.value, props.value.file, props.currentBoardId])
if (imageDataUrl) {
return (
<img
data-testid='image'
className='ImageView'
src={imageDataUrl}
/>
)
}
return null
},
Input: (props: BlockInputProps<FileInfo>) => {
const ref = useRef<HTMLInputElement|null>(null)
useEffect(() => {
ref.current?.click()
}, [])
return (
<div>
{props.value.file && (typeof props.value.file === 'string') && (
<img
className='ImageView'
src={props.value.file}
onClick={() => ref.current?.click()}
/>
)}
<input
ref={ref}
className='Image'
data-testid='image-input'
type='file'
accept='image/*'
onChange={(e) => {
const file = (e.currentTarget?.files || [])[0]
props.onSave({file})
}}
/>
</div>
)
},
}
Image.runSlashCommand = (changeType: (contentType: ContentType<FileInfo>) => void, changeValue: (value: FileInfo) => void): void => {
changeType(Image)
changeValue({file: ''})
}
export default Image