Merge pull request #14495 from overleaf/mj-table-gen-textarea

[visual] Use textarea instead of input in table generator

GitOrigin-RevId: 5d394f9978dc25bebf63f1cbd4f1c39466469843
This commit is contained in:
Mathias Jakobsen 2023-08-29 11:13:56 +01:00 committed by Copybot
parent 575f646dd4
commit a3ee0dcd39
4 changed files with 60 additions and 15 deletions

View file

@ -0,0 +1,33 @@
import { forwardRef, useImperativeHandle, useLayoutEffect, useRef } from 'react'
interface CellInputProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
value: string
}
export type CellInputRef = {
focus: () => void
}
export const CellInput = forwardRef<CellInputRef, CellInputProps>(
function CellInput({ value, ...props }: CellInputProps, ref) {
const inputRef = useRef<HTMLTextAreaElement>(null)
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current?.focus()
inputRef.current?.setSelectionRange(value.length, value.length)
},
}
})
useLayoutEffect(() => {
if (inputRef?.current) {
inputRef.current.style.height = '1px'
inputRef.current.style.height = `${inputRef.current.scrollHeight}px`
}
}, [value])
return <textarea {...props} value={value} ref={inputRef} />
}
)

View file

@ -10,6 +10,7 @@ import { loadMathJax } from '../../../mathjax/load-mathjax'
import { typesetNodeIntoElement } from '../../extensions/visual/utils/typeset-content'
import { parser } from '../../lezer-latex/latex.mjs'
import { useTableContext } from './contexts/table-context'
import { CellInput, CellInputRef } from './cell-input'
export const Cell: FC<{
cellData: CellData
@ -38,7 +39,7 @@ export const Cell: FC<{
startEditing,
commitCellData,
} = useEditingContext()
const inputRef = useRef<HTMLInputElement>(null)
const inputRef = useRef<CellInputRef>(null)
const editing =
editingCellData?.rowIndex === rowIndex &&
@ -48,6 +49,9 @@ export const Cell: FC<{
const onMouseDown: MouseEventHandler = useCallback(
event => {
if (editing) {
return
}
if (event.button !== 0) {
return
}
@ -65,7 +69,7 @@ export const Cell: FC<{
)
})
},
[setDragging, columnIndex, rowIndex, setSelection, table]
[setDragging, columnIndex, rowIndex, setSelection, table, editing]
)
const onMouseUp = useCallback(() => {
@ -117,19 +121,19 @@ export const Cell: FC<{
)
useEffect(() => {
if (editing) {
inputRef.current?.focus()
if (editing && inputRef.current) {
inputRef.current.focus()
}
}, [editing])
}, [editing, cellData.content.length])
const filterInput = (input: string) => {
const filterInput = useCallback((input: string) => {
// TODO: Are there situations where we don't want to filter the input?
return input
.replaceAll(/(^&|[^\\]&)/g, match =>
match.length === 1 ? '\\&' : `${match[0]}\\&`
)
.replaceAll('\\\\', '')
}
}, [])
const isFocused =
selection?.to.row === rowIndex &&
@ -161,18 +165,22 @@ export const Cell: FC<{
}
}, [cellData.content, editing])
const onInput = useCallback(
e => {
update(filterInput(e.target.value))
},
[update, filterInput]
)
let body = <div ref={renderDiv} />
if (editing) {
body = (
<input
<CellInput
className="table-generator-cell-input"
ref={inputRef}
value={editingCellData.content}
onBlur={commitCellData}
style={{ width: `inherit` }}
onChange={e => {
update(filterInput(e.target.value))
}}
onInput={onInput}
ref={inputRef}
/>
)
}

View file

@ -79,7 +79,7 @@ export const Table: FC = () => {
const onKeyDown: KeyboardEventHandler = useCallback(
event => {
if (event.code === 'Enter') {
if (event.code === 'Enter' && !event.shiftKey) {
event.preventDefault()
event.stopPropagation()
if (!selection) {

View file

@ -275,10 +275,14 @@ export const tableGeneratorTheme = EditorView.baseTheme({
'.table-generator-cell-input': {
'max-width': 'calc(200px - 0.5em)',
width: '100%',
'background-color': 'transparent',
width: '100%',
height: '1.5em',
border: '1px solid var(--table-generator-toolbar-shadow-color)',
padding: '0',
resize: 'none',
'box-sizing': 'border-box',
overflow: 'hidden',
},
'.table-generator-border-options-coming-soon': {