mirror of
https://github.com/overleaf/overleaf.git
synced 2025-02-20 22:21:06 +00:00
Merge pull request #14248 from overleaf/mj-table-cell-alignment
[visual] Enable cell alignment in table generator GitOrigin-RevId: 31be50712fd6b3b1da37b0906965f70618f6a9b3
This commit is contained in:
parent
56438c32cc
commit
31c285871a
4 changed files with 74 additions and 10 deletions
services/web/frontend/js/features/source-editor/components/table-generator
|
@ -34,6 +34,7 @@ export type ColumnDefinition = {
|
|||
alignment: 'left' | 'center' | 'right' | 'paragraph'
|
||||
borderLeft: number
|
||||
borderRight: number
|
||||
content: string
|
||||
}
|
||||
|
||||
export type TableData = {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { EditorView } from '@codemirror/view'
|
||||
import { Positions } from '../tabular'
|
||||
import { ColumnDefinition, Positions } from '../tabular'
|
||||
import { ChangeSpec } from '@codemirror/state'
|
||||
import { RowSeparator } from '../utils'
|
||||
import { RowSeparator, parseColumnSpecifications } from '../utils'
|
||||
import { TableSelection } from '../contexts/selection-context'
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
export enum BorderTheme {
|
||||
|
@ -96,3 +97,46 @@ export const setBorders = (
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const setAlignment = (
|
||||
view: EditorView,
|
||||
selection: TableSelection,
|
||||
alignment: 'left' | 'right' | 'center',
|
||||
positions: Positions
|
||||
) => {
|
||||
const specification = view.state.sliceDoc(
|
||||
positions.columnDeclarations.from,
|
||||
positions.columnDeclarations.to
|
||||
)
|
||||
const columnSpecification = parseColumnSpecifications(specification)
|
||||
const { minX, maxX } = selection.normalized()
|
||||
for (let i = minX; i <= maxX; i++) {
|
||||
if (selection.isColumnSelected(i, positions.rowPositions.length)) {
|
||||
if (columnSpecification[i].alignment === alignment) {
|
||||
continue
|
||||
}
|
||||
columnSpecification[i].alignment = alignment
|
||||
// TODO: This won't work for paragraph, which needs width argument
|
||||
columnSpecification[i].content = alignment[0]
|
||||
}
|
||||
}
|
||||
const newSpecification = generateColumnSpecification(columnSpecification)
|
||||
view.dispatch({
|
||||
changes: [
|
||||
{
|
||||
from: positions.columnDeclarations.from,
|
||||
to: positions.columnDeclarations.to,
|
||||
insert: newSpecification,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
const generateColumnSpecification = (columns: ColumnDefinition[]) => {
|
||||
return columns
|
||||
.map(
|
||||
({ borderLeft, borderRight, content }) =>
|
||||
`${'|'.repeat(borderLeft)}${content}${'|'.repeat(borderRight)}`
|
||||
)
|
||||
.join('')
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { ToolbarButton } from './toolbar-button'
|
|||
import { ToolbarButtonMenu } from './toolbar-button-menu'
|
||||
import { ToolbarDropdown } from './toolbar-dropdown'
|
||||
import MaterialIcon from '../../../../../shared/components/material-icon'
|
||||
import { BorderTheme, setBorders } from './commands'
|
||||
import { BorderTheme, setAlignment, setBorders } from './commands'
|
||||
import { useCodeMirrorViewContext } from '../../codemirror-editor'
|
||||
import { useTableContext } from '../contexts/table-context'
|
||||
|
||||
|
@ -87,27 +87,36 @@ export const Toolbar = memo(function Toolbar() {
|
|||
label="Alignment"
|
||||
icon="format_align_left"
|
||||
id="table-generator-align-dropdown"
|
||||
disabled
|
||||
disabled={
|
||||
!selection.isColumnSelected(
|
||||
selection.from.cell,
|
||||
positions.rowPositions.length
|
||||
)
|
||||
}
|
||||
>
|
||||
<ToolbarButton
|
||||
icon="format_align_left"
|
||||
id="table-generator-align-left"
|
||||
label="Left"
|
||||
command={() => {
|
||||
setAlignment(view, selection, 'left', positions)
|
||||
}}
|
||||
/>
|
||||
<ToolbarButton
|
||||
icon="format_align_center"
|
||||
id="table-generator-align-center"
|
||||
label="Center"
|
||||
command={() => {
|
||||
setAlignment(view, selection, 'center', positions)
|
||||
}}
|
||||
/>
|
||||
<ToolbarButton
|
||||
icon="format_align_right"
|
||||
id="table-generator-align-right"
|
||||
label="Right"
|
||||
/>
|
||||
<ToolbarButton
|
||||
icon="format_align_justify"
|
||||
id="table-generator-align-justify"
|
||||
label="Justify"
|
||||
command={() => {
|
||||
setAlignment(view, selection, 'right', positions)
|
||||
}}
|
||||
/>
|
||||
</ToolbarButtonMenu>
|
||||
<ToolbarButton
|
||||
|
|
|
@ -11,21 +11,26 @@ export type RowPosition = {
|
|||
hlines: { from: number; to: number }[]
|
||||
}
|
||||
|
||||
function parseColumnSpecifications(specification: string): ColumnDefinition[] {
|
||||
export function parseColumnSpecifications(
|
||||
specification: string
|
||||
): ColumnDefinition[] {
|
||||
const columns: ColumnDefinition[] = []
|
||||
let currentAlignment: ColumnDefinition['alignment'] | undefined
|
||||
let currentBorderLeft = 0
|
||||
let currentBorderRight = 0
|
||||
let currentContent = ''
|
||||
function maybeCommit() {
|
||||
if (currentAlignment !== undefined) {
|
||||
columns.push({
|
||||
alignment: currentAlignment,
|
||||
borderLeft: currentBorderLeft,
|
||||
borderRight: currentBorderRight,
|
||||
content: currentContent,
|
||||
})
|
||||
currentAlignment = undefined
|
||||
currentBorderLeft = 0
|
||||
currentBorderRight = 0
|
||||
currentContent = ''
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < specification.length; i++) {
|
||||
|
@ -45,18 +50,23 @@ function parseColumnSpecifications(specification: string): ColumnDefinition[] {
|
|||
}
|
||||
case 'c':
|
||||
currentAlignment = 'center'
|
||||
currentContent += 'c'
|
||||
break
|
||||
case 'l':
|
||||
currentAlignment = 'left'
|
||||
currentContent += 'l'
|
||||
break
|
||||
case 'r':
|
||||
currentAlignment = 'right'
|
||||
currentContent += 'r'
|
||||
break
|
||||
case 'p': {
|
||||
currentAlignment = 'paragraph'
|
||||
currentContent += 'p'
|
||||
// TODO: Parse these details
|
||||
while (i < specification.length && specification.charAt(i) !== '}') {
|
||||
i++
|
||||
currentContent += specification.charAt(i)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue