checkboxElement.tsx
TLDR
This file, checkboxElement.tsx
, is part of the Demo Projects project. It contains the implementation of a React component called CheckboxElement
. The component renders a checkbox input element along with an editable title. It allows users to toggle the checkbox state and modify the title. The component also registers itself as a content type with the contentRegistry
module.
Methods
There are no methods defined in this file.
Classes
CheckboxElement
The CheckboxElement
class is a React component that renders a checkbox input element along with an editable title. It has the following props:
-
block
: TheContentBlock
object associated with the element. -
readonly
: A boolean indicating whether the element is in read-only mode. -
onAddElement
(optional): A callback function called when a new element is added. -
onDeleteElement
(optional): A callback function called when the element is deleted.
The CheckboxElement
component maintains its own state for the active state of the checkbox and the current title. It uses the useIntl
hook for internationalization and the useCardDetailContext
hook to access the card detail context.
The component updates its state and triggers the necessary mutations when the checkbox is toggled or the title is modified. It also supports focusing on the title input field when a new element is added.
The CheckboxElement
component is exported as the default export of the file and wrapped in the React.memo
higher-order component.
contentRegistry
The contentRegistry
object is imported from the ./contentRegistry
module. The CheckboxElement
component is registered as a content type with the contentRegistry
using the registerContentType
method. The content type registration specifies the text to be displayed for the content type, the icon to be used, and the functions to create a new block and create a component for rendering the block.
END
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useEffect, useRef, useState} from 'react'
import {useIntl} from 'react-intl'
import {createCheckboxBlock} from '../../blocks/checkboxBlock'
import {ContentBlock} from '../../blocks/contentBlock'
import CheckIcon from '../../widgets/icons/check'
import mutator from '../../mutator'
import Editable, {Focusable} from '../../widgets/editable'
import {useCardDetailContext} from '../cardDetail/cardDetailContext'
import './checkboxElement.scss'
import {contentRegistry} from './contentRegistry'
type Props = {
block: ContentBlock
readonly: boolean
onAddElement?: () => void
onDeleteElement?: () => void
}
const CheckboxElement = (props: Props) => {
const {block, readonly} = props
const intl = useIntl()
const titleRef = useRef<Focusable>(null)
const cardDetail = useCardDetailContext()
const [addedBlockId, setAddedBlockId] = useState(cardDetail.lastAddedBlock.id)
const [active, setActive] = useState(Boolean(block.fields.value))
const [title, setTitle] = useState(block.title)
useEffect(() => {
if (block.id === addedBlockId) {
titleRef.current?.focus()
setAddedBlockId('')
}
}, [block, addedBlockId, titleRef])
useEffect(() => {
setActive(Boolean(block.fields.value))
}, [Boolean(block.fields.value)])
return (
<div className='CheckboxElement'>
<input
type='checkbox'
id={`checkbox-${block.id}`}
disabled={readonly}
checked={active}
value={active ? 'on' : 'off'}
onChange={(e) => {
e.preventDefault()
const newBlock = createCheckboxBlock(block)
newBlock.fields.value = !active
newBlock.title = title
setActive(newBlock.fields.value)
mutator.updateBlock(block.boardId, newBlock, block, intl.formatMessage({id: 'ContentBlock.editCardCheckbox', defaultMessage: 'toggled-checkbox'}))
}}
/>
<Editable
ref={titleRef}
value={title}
placeholderText={intl.formatMessage({id: 'ContentBlock.editText', defaultMessage: 'Edit text...'})}
onChange={setTitle}
saveOnEsc={true}
onSave={async (saveType) => {
const {lastAddedBlock} = cardDetail
if (title === '' && block.id === lastAddedBlock.id && lastAddedBlock.autoAdded && props.onDeleteElement) {
props.onDeleteElement()
return
}
if (block.title !== title) {
await mutator.changeBlockTitle(block.boardId, block.id, block.title, title, intl.formatMessage({id: 'ContentBlock.editCardCheckboxText', defaultMessage: 'edit card text'}))
if (saveType === 'onEnter' && title !== '' && props.onAddElement) {
// Wait for the change to happen
setTimeout(props.onAddElement, 100)
}
return
}
if (saveType === 'onEnter' && title !== '' && props.onAddElement) {
props.onAddElement()
}
}}
readonly={readonly}
spellCheck={true}
/>
</div>
)
}
contentRegistry.registerContentType({
type: 'checkbox',
getDisplayText: (intl) => intl.formatMessage({id: 'ContentBlock.checkbox', defaultMessage: 'checkbox'}),
getIcon: () => <CheckIcon/>,
createBlock: async () => {
return createCheckboxBlock()
},
createComponent: (block, readonly, onAddElement, onDeleteElement) => {
return (
<CheckboxElement
block={block}
readonly={readonly}
onAddElement={onAddElement}
onDeleteElement={onDeleteElement}
/>
)
},
})
export default React.memo(CheckboxElement)