mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #14428 from overleaf/mj-table-gen-cleanup
[visual] Table generator tweaks and improvements GitOrigin-RevId: 621820c613924bc201ec85ea249edd6c9b6f88b2
This commit is contained in:
parent
b987e59d60
commit
8b5278c076
14 changed files with 593 additions and 420 deletions
|
@ -36,6 +36,7 @@ export const Cell: FC<{
|
||||||
cellData: editingCellData,
|
cellData: editingCellData,
|
||||||
updateCellData: update,
|
updateCellData: update,
|
||||||
startEditing,
|
startEditing,
|
||||||
|
commitCellData,
|
||||||
} = useEditingContext()
|
} = useEditingContext()
|
||||||
const inputRef = useRef<HTMLInputElement>(null)
|
const inputRef = useRef<HTMLInputElement>(null)
|
||||||
|
|
||||||
|
@ -167,6 +168,7 @@ export const Cell: FC<{
|
||||||
className="table-generator-cell-input"
|
className="table-generator-cell-input"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
value={editingCellData.content}
|
value={editingCellData.content}
|
||||||
|
onBlur={commitCellData}
|
||||||
style={{ width: `inherit` }}
|
style={{ width: `inherit` }}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
update(filterInput(e.target.value))
|
update(filterInput(e.target.value))
|
||||||
|
|
|
@ -333,6 +333,17 @@ export class TableSelection {
|
||||||
const { minY, maxY } = this.normalized()
|
const { minY, maxY } = this.normalized()
|
||||||
return maxY - minY + 1
|
return maxY - minY + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maximumCellWidth(table: TableData) {
|
||||||
|
const { minX, maxX, minY, maxY } = this.normalized()
|
||||||
|
let maxWidth = 1
|
||||||
|
for (let row = minY; row <= maxY; ++row) {
|
||||||
|
const start = table.getCellIndex(row, minX)
|
||||||
|
const end = table.getCellIndex(row, maxX)
|
||||||
|
maxWidth = Math.max(maxWidth, end - start + 1)
|
||||||
|
}
|
||||||
|
return maxWidth
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectionContext = createContext<
|
const SelectionContext = createContext<
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { CodeMirrorViewContextProvider } from '../codemirror-editor'
|
||||||
import { TableProvider } from './contexts/table-context'
|
import { TableProvider } from './contexts/table-context'
|
||||||
import { TabularProvider, useTabularContext } from './contexts/tabular-context'
|
import { TabularProvider, useTabularContext } from './contexts/tabular-context'
|
||||||
import Icon from '../../../../shared/components/icon'
|
import Icon from '../../../../shared/components/icon'
|
||||||
|
import { BorderTheme } from './toolbar/commands'
|
||||||
|
|
||||||
export type ColumnDefinition = {
|
export type ColumnDefinition = {
|
||||||
alignment: 'left' | 'center' | 'right' | 'paragraph'
|
alignment: 'left' | 'center' | 'right' | 'paragraph'
|
||||||
|
@ -91,6 +92,56 @@ export class TableData {
|
||||||
}
|
}
|
||||||
throw new Error("Couldn't find cell boundaries")
|
throw new Error("Couldn't find cell boundaries")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBorderTheme(): BorderTheme | null {
|
||||||
|
if (this.rows.length === 0 || this.columns.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const lastRow = this.rows[this.rows.length - 1]
|
||||||
|
const hasBottomBorder = lastRow.borderBottom > 0
|
||||||
|
const firstColumn = this.columns[0]
|
||||||
|
const hasLeftBorder = firstColumn.borderLeft > 0
|
||||||
|
for (const row of this.rows) {
|
||||||
|
if (hasBottomBorder === (row.borderTop === 0)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we had the first, we have verified that we have the rest
|
||||||
|
const hasAllRowBorders = hasBottomBorder
|
||||||
|
|
||||||
|
for (const column of this.columns) {
|
||||||
|
if (hasLeftBorder === (column.borderRight === 0)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const row of this.rows) {
|
||||||
|
for (const cell of row.cells) {
|
||||||
|
if (cell.multiColumn) {
|
||||||
|
if (cell.multiColumn.columns.specification.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const firstCell = cell.multiColumn.columns.specification[0]
|
||||||
|
if (hasLeftBorder === (firstCell.borderLeft === 0)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
for (const column of cell.multiColumn.columns.specification) {
|
||||||
|
if (hasLeftBorder === (column.borderRight === 0)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we had the first, we have verified that we have the rest
|
||||||
|
const hasAllColumnBorders = hasLeftBorder
|
||||||
|
|
||||||
|
if (hasAllRowBorders && hasAllColumnBorders) {
|
||||||
|
return BorderTheme.FULLY_BORDERED
|
||||||
|
} else {
|
||||||
|
return BorderTheme.NO_BORDERS
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Positions = {
|
export type Positions = {
|
||||||
|
|
|
@ -342,13 +342,21 @@ export const insertRow = (
|
||||||
below: boolean,
|
below: boolean,
|
||||||
table: TableData
|
table: TableData
|
||||||
) => {
|
) => {
|
||||||
// TODO: Handle borders
|
|
||||||
const { maxY, minY } = selection.normalized()
|
const { maxY, minY } = selection.normalized()
|
||||||
|
const rowsToInsert = selection.height()
|
||||||
const from = below
|
const from = below
|
||||||
? positions.rowPositions[maxY].to
|
? positions.rowPositions[maxY].to
|
||||||
: positions.rowPositions[minY].from
|
: positions.rowPositions[minY].from
|
||||||
const numberOfColumns = table.columns.length
|
const numberOfColumns = table.columns.length
|
||||||
const insert = `\n${' &'.repeat(numberOfColumns - 1)}\\\\`
|
const borderTheme = table.getBorderTheme()
|
||||||
|
const border = borderTheme === BorderTheme.FULLY_BORDERED ? '\\hline' : ''
|
||||||
|
const initialHline =
|
||||||
|
borderTheme === BorderTheme.FULLY_BORDERED && !below && minY === 0
|
||||||
|
? '\\hline'
|
||||||
|
: ''
|
||||||
|
const insert = `${initialHline}\n${' &'.repeat(
|
||||||
|
numberOfColumns - 1
|
||||||
|
)}\\\\${border}`.repeat(rowsToInsert)
|
||||||
view.dispatch({ changes: { from, to: from, insert } })
|
view.dispatch({ changes: { from, to: from, insert } })
|
||||||
if (!below) {
|
if (!below) {
|
||||||
return selection
|
return selection
|
||||||
|
@ -366,9 +374,9 @@ export const insertColumn = (
|
||||||
after: boolean,
|
after: boolean,
|
||||||
table: TableData
|
table: TableData
|
||||||
) => {
|
) => {
|
||||||
// TODO: Handle borders
|
|
||||||
const selection = initialSelection.explode(table)
|
const selection = initialSelection.explode(table)
|
||||||
const { maxX, minX } = selection.normalized()
|
const { maxX, minX } = selection.normalized()
|
||||||
|
const columnsToInsert = selection.maximumCellWidth(table)
|
||||||
const changes: ChangeSpec[] = []
|
const changes: ChangeSpec[] = []
|
||||||
const targetColumn = after ? maxX : minX
|
const targetColumn = after ? maxX : minX
|
||||||
for (let row = 0; row < positions.rowPositions.length; row++) {
|
for (let row = 0; row < positions.rowPositions.length; row++) {
|
||||||
|
@ -377,7 +385,7 @@ export const insertColumn = (
|
||||||
const from = after ? target.to : target.from
|
const from = after ? target.to : target.from
|
||||||
changes.push({
|
changes.push({
|
||||||
from,
|
from,
|
||||||
insert: ' &',
|
insert: ' &'.repeat(columnsToInsert),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,12 +394,25 @@ export const insertColumn = (
|
||||||
positions.columnDeclarations.to
|
positions.columnDeclarations.to
|
||||||
)
|
)
|
||||||
const columnSpecification = parseColumnSpecifications(specification)
|
const columnSpecification = parseColumnSpecifications(specification)
|
||||||
columnSpecification.splice(after ? maxX + 1 : minX, 0, {
|
const borderTheme = table.getBorderTheme()
|
||||||
alignment: 'left',
|
const borderRight = borderTheme === BorderTheme.FULLY_BORDERED ? 1 : 0
|
||||||
|
const targetIndex = after ? maxX + 1 : minX
|
||||||
|
columnSpecification.splice(
|
||||||
|
targetIndex,
|
||||||
|
0,
|
||||||
|
...Array.from({ length: columnsToInsert }, () => ({
|
||||||
|
alignment: 'left' as const,
|
||||||
borderLeft: 0,
|
borderLeft: 0,
|
||||||
borderRight: 0,
|
borderRight,
|
||||||
content: 'l',
|
content: 'l',
|
||||||
})
|
}))
|
||||||
|
)
|
||||||
|
if (targetIndex === 0 && borderTheme === BorderTheme.FULLY_BORDERED) {
|
||||||
|
columnSpecification[0].borderLeft = Math.max(
|
||||||
|
1,
|
||||||
|
columnSpecification[0].borderLeft
|
||||||
|
)
|
||||||
|
}
|
||||||
changes.push({
|
changes.push({
|
||||||
from: positions.columnDeclarations.from,
|
from: positions.columnDeclarations.from,
|
||||||
to: positions.columnDeclarations.to,
|
to: positions.columnDeclarations.to,
|
||||||
|
@ -581,8 +602,9 @@ export const mergeCells = (
|
||||||
cellContent.push(table.getCell(minY, i).content)
|
cellContent.push(table.getCell(minY, i).content)
|
||||||
}
|
}
|
||||||
const content = cellContent.join(' ').trim()
|
const content = cellContent.join(' ').trim()
|
||||||
// TODO: respect border theme
|
const border =
|
||||||
const preamble = '\\multicolumn{' + (maxX - minX + 1) + '}{c}{'
|
table.getBorderTheme() === BorderTheme.FULLY_BORDERED ? '|' : ''
|
||||||
|
const preamble = `\\multicolumn{${maxX - minX + 1}}{${border}c${border}}{`
|
||||||
const postamble = '}'
|
const postamble = '}'
|
||||||
const { from } = table.getCell(minY, minX)
|
const { from } = table.getCell(minY, minX)
|
||||||
const { to } = table.getCell(minY, maxX)
|
const { to } = table.getCell(minY, maxX)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { memo } from 'react'
|
import { memo, useMemo } from 'react'
|
||||||
import { useSelectionContext } from '../contexts/selection-context'
|
import { useSelectionContext } from '../contexts/selection-context'
|
||||||
import { ToolbarButton } from './toolbar-button'
|
import { ToolbarButton } from './toolbar-button'
|
||||||
import { ToolbarButtonMenu } from './toolbar-button-menu'
|
import { ToolbarButtonMenu } from './toolbar-button-menu'
|
||||||
|
@ -20,19 +20,49 @@ import {
|
||||||
import { useCodeMirrorViewContext } from '../../codemirror-editor'
|
import { useCodeMirrorViewContext } from '../../codemirror-editor'
|
||||||
import { useTableContext } from '../contexts/table-context'
|
import { useTableContext } from '../contexts/table-context'
|
||||||
|
|
||||||
|
const borderThemeLabel = (theme: BorderTheme | null) => {
|
||||||
|
switch (theme) {
|
||||||
|
case BorderTheme.FULLY_BORDERED:
|
||||||
|
return 'All borders'
|
||||||
|
case BorderTheme.NO_BORDERS:
|
||||||
|
return 'No borders'
|
||||||
|
default:
|
||||||
|
return 'Custom borders'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const Toolbar = memo(function Toolbar() {
|
export const Toolbar = memo(function Toolbar() {
|
||||||
const { selection, setSelection } = useSelectionContext()
|
const { selection, setSelection } = useSelectionContext()
|
||||||
const view = useCodeMirrorViewContext()
|
const view = useCodeMirrorViewContext()
|
||||||
const { positions, rowSeparators, cellSeparators, tableEnvironment, table } =
|
const { positions, rowSeparators, cellSeparators, tableEnvironment, table } =
|
||||||
useTableContext()
|
useTableContext()
|
||||||
|
|
||||||
|
const borderDropdownLabel = useMemo(
|
||||||
|
() => borderThemeLabel(table.getBorderTheme()),
|
||||||
|
[table]
|
||||||
|
)
|
||||||
|
|
||||||
|
const captionLabel = useMemo(() => {
|
||||||
|
if (!tableEnvironment?.caption) {
|
||||||
|
return 'No caption'
|
||||||
|
}
|
||||||
|
if (tableEnvironment.caption.from < positions.tabular.from) {
|
||||||
|
return 'Caption above'
|
||||||
|
}
|
||||||
|
return 'Caption below'
|
||||||
|
}, [tableEnvironment, positions.tabular.from])
|
||||||
|
|
||||||
if (!selection) {
|
if (!selection) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
const columnsToInsert = selection.maximumCellWidth(table)
|
||||||
|
const rowsToInsert = selection.height()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="table-generator-floating-toolbar">
|
<div className="table-generator-floating-toolbar">
|
||||||
<ToolbarDropdown
|
<ToolbarDropdown
|
||||||
id="table-generator-caption-dropdown"
|
id="table-generator-caption-dropdown"
|
||||||
label="Caption below"
|
label={captionLabel}
|
||||||
disabled={!tableEnvironment}
|
disabled={!tableEnvironment}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
@ -68,7 +98,7 @@ export const Toolbar = memo(function Toolbar() {
|
||||||
</ToolbarDropdown>
|
</ToolbarDropdown>
|
||||||
<ToolbarDropdown
|
<ToolbarDropdown
|
||||||
id="table-generator-borders-dropdown"
|
id="table-generator-borders-dropdown"
|
||||||
label="All borders"
|
label={borderDropdownLabel}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
className="ol-cm-toolbar-menu-item"
|
className="ol-cm-toolbar-menu-item"
|
||||||
|
@ -209,7 +239,9 @@ export const Toolbar = memo(function Toolbar() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="table-generator-button-label">
|
<span className="table-generator-button-label">
|
||||||
Insert column left
|
{columnsToInsert === 1
|
||||||
|
? 'Insert column left'
|
||||||
|
: `Insert ${columnsToInsert} columns left`}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@ -223,7 +255,9 @@ export const Toolbar = memo(function Toolbar() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="table-generator-button-label">
|
<span className="table-generator-button-label">
|
||||||
Insert column right
|
{columnsToInsert === 1
|
||||||
|
? 'Insert column right'
|
||||||
|
: `Insert ${columnsToInsert} columns right`}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -236,7 +270,9 @@ export const Toolbar = memo(function Toolbar() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="table-generator-button-label">
|
<span className="table-generator-button-label">
|
||||||
Insert row above
|
{rowsToInsert === 1
|
||||||
|
? 'Insert row above'
|
||||||
|
: `Insert ${rowsToInsert} rows above`}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@ -248,7 +284,9 @@ export const Toolbar = memo(function Toolbar() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="table-generator-button-label">
|
<span className="table-generator-button-label">
|
||||||
Insert row below
|
{rowsToInsert === 1
|
||||||
|
? 'Insert row below'
|
||||||
|
: `Insert ${rowsToInsert} rows below`}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</ToolbarDropdown>
|
</ToolbarDropdown>
|
||||||
|
@ -260,6 +298,7 @@ export const Toolbar = memo(function Toolbar() {
|
||||||
label="Delete table"
|
label="Delete table"
|
||||||
command={() => {
|
command={() => {
|
||||||
removeNodes(view, tableEnvironment?.table ?? positions.tabular)
|
removeNodes(view, tableEnvironment?.table ?? positions.tabular)
|
||||||
|
view.focus()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -213,7 +213,7 @@ function parseTabularBody(
|
||||||
if (!tabularArgument) {
|
if (!tabularArgument) {
|
||||||
throw new Error('Invalid multicolumn definition: missing cell content')
|
throw new Error('Invalid multicolumn definition: missing cell content')
|
||||||
}
|
}
|
||||||
if (getLastCell()?.content) {
|
if (getLastCell()?.content.trim()) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Invalid multicolumn definition: multicolumn must be at the start of a cell'
|
'Invalid multicolumn definition: multicolumn must be at the start of a cell'
|
||||||
)
|
)
|
||||||
|
|
|
@ -109,7 +109,7 @@ const SizeGrid: FC<{
|
||||||
onMouseEnter={() => {
|
onMouseEnter={() => {
|
||||||
setCurrentSize({ sizeX: x, sizeY: y })
|
setCurrentSize({ sizeX: x, sizeY: y })
|
||||||
}}
|
}}
|
||||||
onMouseDown={() => onSizeSelected(x, y)}
|
onMouseUp={() => onSizeSelected(x, y)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -71,7 +71,7 @@ export const insertFigure: Command = view => {
|
||||||
export const insertTable = (view: EditorView, sizeX: number, sizeY: number) => {
|
export const insertTable = (view: EditorView, sizeX: number, sizeY: number) => {
|
||||||
const { state, dispatch } = view
|
const { state, dispatch } = view
|
||||||
const { pos, suffix } = ensureEmptyLine(state, state.selection.main)
|
const { pos, suffix } = ensureEmptyLine(state, state.selection.main)
|
||||||
const template = `\n\\begin{table}{#{}}
|
const template = `\n\\begin{table}[#{}]
|
||||||
\t\\centering
|
\t\\centering
|
||||||
\\begin{tabular}{${'c'.repeat(sizeX)}}
|
\\begin{tabular}{${'c'.repeat(sizeX)}}
|
||||||
${('\t\t' + '#{} & #{}'.repeat(sizeX - 1) + '\\\\\n').repeat(
|
${('\t\t' + '#{} & #{}'.repeat(sizeX - 1) + '\\\\\n').repeat(
|
||||||
|
|
|
@ -255,6 +255,15 @@ export const toolbarPanel = () => [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'&.overall-theme-dark .ol-cm-toolbar-table-grid-popover': {
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
'&.overall-theme-dark .ol-cm-toolbar-table-grid': {
|
||||||
|
'& td.active': {
|
||||||
|
outlineColor: 'white',
|
||||||
|
background: 'rgb(125, 125, 125)',
|
||||||
|
},
|
||||||
|
},
|
||||||
'.ol-cm-toolbar-table-grid': {
|
'.ol-cm-toolbar-table-grid': {
|
||||||
borderCollapse: 'separate',
|
borderCollapse: 'separate',
|
||||||
tableLayout: 'fixed',
|
tableLayout: 'fixed',
|
||||||
|
@ -281,6 +290,7 @@ export const toolbarPanel = () => [
|
||||||
'.ol-cm-toolbar-table-grid-popover': {
|
'.ol-cm-toolbar-table-grid-popover': {
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
marginLeft: '80px',
|
marginLeft: '80px',
|
||||||
|
backgroundColor: 'var(--editor-toolbar-bg)',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,424 @@
|
||||||
|
import { EditorView } from '@codemirror/view'
|
||||||
|
|
||||||
|
export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
|
'&dark .table-generator': {
|
||||||
|
'--table-generator-active-border-color': '#ccc',
|
||||||
|
'--table-generator-coming-soon-background-color': '#41464f',
|
||||||
|
'--table-generator-coming-soon-color': '#fff',
|
||||||
|
'--table-generator-divider-color': 'rgba(125,125,125,0.3)',
|
||||||
|
'--table-generator-dropdown-divider-color': 'rgba(125,125,125,0.3)',
|
||||||
|
'--table-generator-focus-border-color': '#5d7498',
|
||||||
|
'--table-generator-inactive-border-color': '#888',
|
||||||
|
'--table-generator-selected-background-color': '#ffffff2a',
|
||||||
|
'--table-generator-selector-background-color': '#777',
|
||||||
|
'--table-generator-selector-hover-color': '#3265b2',
|
||||||
|
'--table-generator-toolbar-background': 'var(--editor-toolbar-bg)',
|
||||||
|
'--table-generator-toolbar-button-active-background':
|
||||||
|
'rgba(125, 125, 125, 0.4)',
|
||||||
|
'--table-generator-toolbar-button-color': 'var(--toolbar-btn-color)',
|
||||||
|
'--table-generator-toolbar-button-hover-background':
|
||||||
|
'rgba(125, 125, 125, 0.2)',
|
||||||
|
'--table-generator-toolbar-dropdown-border-color': 'rgba(125,125,125,0.3)',
|
||||||
|
'--table-generator-toolbar-dropdown-disabled-background':
|
||||||
|
'rgba(125,125,125,0.3)',
|
||||||
|
'--table-generator-toolbar-dropdown-disabled-color': '#999',
|
||||||
|
'--table-generator-toolbar-shadow-color': '#1e253029',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&light .table-generator': {
|
||||||
|
'--table-generator-active-border-color': '#666',
|
||||||
|
'--table-generator-coming-soon-background-color': 'var(--neutral-10)',
|
||||||
|
'--table-generator-coming-soon-color': 'var(--neutral-70)',
|
||||||
|
'--table-generator-divider-color': 'var(--neutral-20)',
|
||||||
|
'--table-generator-dropdown-divider-color': 'var(--neutral-20)',
|
||||||
|
'--table-generator-focus-border-color': '#97b6e5',
|
||||||
|
'--table-generator-inactive-border-color': '#dedede',
|
||||||
|
'--table-generator-selected-background-color': 'var(--blue-10)',
|
||||||
|
'--table-generator-selector-background-color': 'var(--neutral-30)',
|
||||||
|
'--table-generator-selector-hover-color': '#3265b2',
|
||||||
|
'--table-generator-toolbar-background': '#fff',
|
||||||
|
'--table-generator-toolbar-button-active-background':
|
||||||
|
'rgba(47, 58, 76, 0.16)',
|
||||||
|
'--table-generator-toolbar-button-color': 'var(--neutral-70)',
|
||||||
|
'--table-generator-toolbar-button-hover-background':
|
||||||
|
'rgba(47, 58, 76, 0.08)',
|
||||||
|
'--table-generator-toolbar-dropdown-border-color': 'var(--neutral-60)',
|
||||||
|
'--table-generator-toolbar-dropdown-disabled-background': '#f2f2f2',
|
||||||
|
'--table-generator-toolbar-dropdown-disabled-color': 'var(--neutral-40)',
|
||||||
|
'--table-generator-toolbar-shadow-color': '#1e253029',
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator': {
|
||||||
|
position: 'relative',
|
||||||
|
'--table-generator-inactive-border-width': '1px',
|
||||||
|
'--table-generator-active-border-width': '1px',
|
||||||
|
'--table-generator-selector-handle-buffer': '12px',
|
||||||
|
'--table-generator-focus-border-width': '2px',
|
||||||
|
'--table-generator-focus-negative-border-width': '-2px',
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-cell.selected': {
|
||||||
|
'background-color': 'var(--table-generator-selected-background-color)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-cell:focus-visible': {
|
||||||
|
outline: '2px dotted var(--table-generator-focus-border-color)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-cell': {
|
||||||
|
border:
|
||||||
|
'var(--table-generator-inactive-border-width) dashed var(--table-generator-inactive-border-color)',
|
||||||
|
'min-width': '40px',
|
||||||
|
height: '30px',
|
||||||
|
'&.selection-edge-top': {
|
||||||
|
'--shadow-top':
|
||||||
|
'0 var(--table-generator-focus-negative-border-width) 0 var(--table-generator-focus-border-color)',
|
||||||
|
},
|
||||||
|
'&.selection-edge-bottom': {
|
||||||
|
'--shadow-bottom':
|
||||||
|
'0 var(--table-generator-focus-border-width) 0 var(--table-generator-focus-border-color)',
|
||||||
|
},
|
||||||
|
'&.selection-edge-left': {
|
||||||
|
'--shadow-left':
|
||||||
|
'var(--table-generator-focus-negative-border-width) 0 0 var(--table-generator-focus-border-color)',
|
||||||
|
},
|
||||||
|
'&.selection-edge-right': {
|
||||||
|
'--shadow-right':
|
||||||
|
'var(--table-generator-focus-border-width) 0 0 var(--table-generator-focus-border-color)',
|
||||||
|
},
|
||||||
|
'box-shadow':
|
||||||
|
'var(--shadow-top, 0 0 0 transparent), var(--shadow-bottom, 0 0 0 transparent), var(--shadow-left, 0 0 0 transparent), var(--shadow-right, 0 0 0 transparent)',
|
||||||
|
'&.table-generator-cell-border-left': {
|
||||||
|
'border-left-style': 'solid',
|
||||||
|
'border-left-color': 'var(--table-generator-active-border-color)',
|
||||||
|
'border-left-width': 'var(--table-generator-active-border-width)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&.table-generator-cell-border-right': {
|
||||||
|
'border-right-style': 'solid',
|
||||||
|
'border-right-color': 'var(--table-generator-active-border-color)',
|
||||||
|
'border-right-width': 'var(--table-generator-active-border-width)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&.table-generator-row-border-top': {
|
||||||
|
'border-top-style': 'solid',
|
||||||
|
'border-top-color': 'var(--table-generator-active-border-color)',
|
||||||
|
'border-top-width': 'var(--table-generator-active-border-width)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&.table-generator-row-border-bottom': {
|
||||||
|
'border-bottom-style': 'solid',
|
||||||
|
'border-bottom-color': 'var(--table-generator-active-border-color)',
|
||||||
|
'border-bottom-width': 'var(--table-generator-active-border-width)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-table': {
|
||||||
|
'table-layout': 'fixed',
|
||||||
|
'max-width': '80%',
|
||||||
|
margin: '0 auto',
|
||||||
|
cursor: 'default',
|
||||||
|
|
||||||
|
'& td': {
|
||||||
|
padding: '0 0.25em',
|
||||||
|
'max-width': '200px',
|
||||||
|
|
||||||
|
'&.alignment-left': {
|
||||||
|
'text-align': 'left',
|
||||||
|
},
|
||||||
|
'&.alignment-right': {
|
||||||
|
'text-align': 'right',
|
||||||
|
},
|
||||||
|
'&.alignment-center': {
|
||||||
|
'text-align': 'center',
|
||||||
|
},
|
||||||
|
'&.alignment-paragraph': {
|
||||||
|
'text-align': 'justify',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'& .table-generator-selector-cell': {
|
||||||
|
padding: '0',
|
||||||
|
border: 'none !important',
|
||||||
|
position: 'relative',
|
||||||
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
'&.row-selector': {
|
||||||
|
width: 'calc(var(--table-generator-selector-handle-buffer) + 8px)',
|
||||||
|
|
||||||
|
'&::after': {
|
||||||
|
width: '4px',
|
||||||
|
height: 'calc(100% - 8px)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&.column-selector': {
|
||||||
|
height: 'calc(var(--table-generator-selector-handle-buffer) + 8px)',
|
||||||
|
|
||||||
|
'&::after': {
|
||||||
|
width: 'calc(100% - 8px)',
|
||||||
|
height: '4px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&::after': {
|
||||||
|
content: '""',
|
||||||
|
display: 'block',
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '4px',
|
||||||
|
right: '4px',
|
||||||
|
width: 'calc(100% - 8px)',
|
||||||
|
height: 'calc(100% - 8px)',
|
||||||
|
'background-color': 'var(--table-generator-selector-background-color)',
|
||||||
|
'border-radius': '4px',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:hover::after': {
|
||||||
|
'background-color': 'var(--table-generator-selector-hover-color)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&.fully-selected::after': {
|
||||||
|
'background-color': 'var(--table-generator-selector-hover-color)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-floating-toolbar': {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '-36px',
|
||||||
|
left: '0',
|
||||||
|
right: '0',
|
||||||
|
margin: '0 auto',
|
||||||
|
'z-index': '1',
|
||||||
|
'border-radius': '4px',
|
||||||
|
width: 'max-content',
|
||||||
|
'background-color': 'var(--table-generator-toolbar-background)',
|
||||||
|
'box-shadow': '0px 2px 4px 0px var(--table-generator-toolbar-shadow-color)',
|
||||||
|
padding: '4px',
|
||||||
|
height: '40px',
|
||||||
|
display: 'flex',
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-toolbar-button': {
|
||||||
|
display: 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'center',
|
||||||
|
margin: '0',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
border: 'none',
|
||||||
|
'border-radius': '4px',
|
||||||
|
'line-height': '1',
|
||||||
|
overflow: 'hidden',
|
||||||
|
color: 'var(--table-generator-toolbar-button-color)',
|
||||||
|
'text-align': 'center',
|
||||||
|
padding: '4px',
|
||||||
|
|
||||||
|
'&:not(first-child)': {
|
||||||
|
'margin-left': '4px',
|
||||||
|
},
|
||||||
|
'&:not(:last-child)': {
|
||||||
|
'margin-right': '4px',
|
||||||
|
},
|
||||||
|
|
||||||
|
'& > span': {
|
||||||
|
'font-size': '24px',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:hover, &:focus': {
|
||||||
|
'background-color':
|
||||||
|
'var(--table-generator-toolbar-button-hover-background)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:active, &.active': {
|
||||||
|
'background-color':
|
||||||
|
'var(--table-generator-toolbar-button-active-background)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:hover, &:focus, &:active, &.active': {
|
||||||
|
'box-shadow': 'none',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&[aria-disabled="true"]': {
|
||||||
|
'&:hover, &:focus, &:active, &.active': {
|
||||||
|
'background-color': 'transparent',
|
||||||
|
},
|
||||||
|
opacity: '0.2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-button-group': {
|
||||||
|
display: 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'center',
|
||||||
|
'line-height': '1',
|
||||||
|
overflow: 'hidden',
|
||||||
|
'&:not(:first-child)': {
|
||||||
|
'border-left': '1px solid var(--table-generator-divider-color)',
|
||||||
|
'padding-left': '8px',
|
||||||
|
'margin-left': '8px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-button-menu-popover': {
|
||||||
|
'background-color': 'var(--table-generator-toolbar-background) !important',
|
||||||
|
'& .popover-content': {
|
||||||
|
padding: '4px',
|
||||||
|
},
|
||||||
|
'& .list-group': {
|
||||||
|
margin: '0',
|
||||||
|
padding: '0',
|
||||||
|
},
|
||||||
|
'& > .arrow': {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-cell-input': {
|
||||||
|
'max-width': 'calc(200px - 0.5em)',
|
||||||
|
width: '100%',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
border: '1px solid var(--table-generator-toolbar-shadow-color)',
|
||||||
|
padding: '0',
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-border-options-coming-soon': {
|
||||||
|
display: 'flex',
|
||||||
|
margin: '4px',
|
||||||
|
'font-size': '12px',
|
||||||
|
background: 'var(--table-generator-coming-soon-background-color)',
|
||||||
|
color: 'var(--table-generator-coming-soon-color)',
|
||||||
|
padding: '8px',
|
||||||
|
gap: '6px',
|
||||||
|
'align-items': 'flex-start',
|
||||||
|
'max-width': '240px',
|
||||||
|
'font-family': 'Lato',
|
||||||
|
|
||||||
|
'& .info-icon': {
|
||||||
|
flex: ' 0 0 24px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-toolbar-dropdown-toggle': {
|
||||||
|
border: '1px solid var(--table-generator-toolbar-dropdown-border-color)',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
background: 'transparent',
|
||||||
|
'white-space': 'nowrap',
|
||||||
|
color: 'var(--table-generator-toolbar-button-color)',
|
||||||
|
'border-radius': '4px',
|
||||||
|
padding: '6px 8px',
|
||||||
|
gap: '8px',
|
||||||
|
'min-width': '120px',
|
||||||
|
'font-size': '14px',
|
||||||
|
display: 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'space-between',
|
||||||
|
'font-family': 'Lato',
|
||||||
|
|
||||||
|
'&:not(:first-child)': {
|
||||||
|
'margin-left': '8px',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&[aria-disabled="true"]': {
|
||||||
|
'background-color':
|
||||||
|
'var(--table-generator-toolbar-dropdown-disabled-background)',
|
||||||
|
color: 'var(--table-generator-toolbar-dropdown-disabled-color)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-toolbar-dropdown-popover': {
|
||||||
|
'max-width': '300px',
|
||||||
|
background: 'var(--table-generator-toolbar-background) !important',
|
||||||
|
|
||||||
|
'& .popover-content': {
|
||||||
|
padding: '0',
|
||||||
|
},
|
||||||
|
|
||||||
|
'& > .arrow': {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-toolbar-dropdown-menu': {
|
||||||
|
display: 'flex',
|
||||||
|
'flex-direction': 'column',
|
||||||
|
'min-width': '200px',
|
||||||
|
|
||||||
|
'& > button': {
|
||||||
|
border: 'none',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
background: 'transparent',
|
||||||
|
'white-space': 'nowrap',
|
||||||
|
color: 'var(--table-generator-toolbar-button-color)',
|
||||||
|
'border-radius': '0',
|
||||||
|
'font-size': '14px',
|
||||||
|
display: 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'space-between',
|
||||||
|
'column-gap': '8px',
|
||||||
|
'align-self': 'stretch',
|
||||||
|
padding: '12px 8px',
|
||||||
|
'font-family': 'Lato',
|
||||||
|
|
||||||
|
'& .table-generator-button-label': {
|
||||||
|
'align-self': 'stretch',
|
||||||
|
flex: '1 0 auto',
|
||||||
|
'text-align': 'left',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:hover, &:focus': {
|
||||||
|
'background-color':
|
||||||
|
'var(--table-generator-toolbar-button-hover-background)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:active, &.active': {
|
||||||
|
'background-color':
|
||||||
|
'var(--table-generator-toolbar-button-active-background)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:hover, &:focus, &:active, &.active': {
|
||||||
|
'box-shadow': 'none',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&[aria-disabled="true"]': {
|
||||||
|
'&:hover, &:focus, &:active, &.active': {
|
||||||
|
'background-color': 'transparent',
|
||||||
|
},
|
||||||
|
color: 'var(--table-generator-toolbar-dropdown-disabled-color)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'& > hr': {
|
||||||
|
background: 'var(--table-generator-dropdown-divider-color)',
|
||||||
|
margin: '2px 8px',
|
||||||
|
display: 'block',
|
||||||
|
'box-sizing': 'content-box',
|
||||||
|
border: '0',
|
||||||
|
height: '1px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-error': {
|
||||||
|
background:
|
||||||
|
'linear-gradient(0deg, #f9f1f1, #f9f1f1), linear-gradient(0deg, #f5beba, #f5beba)',
|
||||||
|
display: 'flex',
|
||||||
|
'justify-content': 'space-between',
|
||||||
|
color: 'black',
|
||||||
|
border: '1px solid #f5beba',
|
||||||
|
'font-family': 'Lato',
|
||||||
|
'margin-bottom': '0',
|
||||||
|
'& .table-generator-error-message': {
|
||||||
|
flex: '1 0 auto',
|
||||||
|
},
|
||||||
|
'& .table-generator-error-icon': {
|
||||||
|
color: '#b83a33',
|
||||||
|
'margin-right': '12px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'.table-generator-filler-row': {
|
||||||
|
border: 'none !important',
|
||||||
|
'& td': {
|
||||||
|
'min-width': '40px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
|
@ -26,6 +26,7 @@ import { toolbarPanel } from '../toolbar/toolbar-panel'
|
||||||
import { selectDecoratedArgument } from './select-decorated-argument'
|
import { selectDecoratedArgument } from './select-decorated-argument'
|
||||||
import { pasteHtml } from './paste-html'
|
import { pasteHtml } from './paste-html'
|
||||||
import { commandTooltip } from '../command-tooltip'
|
import { commandTooltip } from '../command-tooltip'
|
||||||
|
import { tableGeneratorTheme } from './table-generator'
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
visual: boolean
|
visual: boolean
|
||||||
|
@ -208,4 +209,5 @@ const extension = (options: Options) => [
|
||||||
showContentWhenParsed,
|
showContentWhenParsed,
|
||||||
figureModalPasteHandler(),
|
figureModalPasteHandler(),
|
||||||
isSplitTestEnabled('paste-html') ? pasteHtml : [],
|
isSplitTestEnabled('paste-html') ? pasteHtml : [],
|
||||||
|
isSplitTestEnabled('table-generator') ? tableGeneratorTheme : [],
|
||||||
]
|
]
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
@import './editor/dictionary.less';
|
@import './editor/dictionary.less';
|
||||||
@import './editor/compile-button.less';
|
@import './editor/compile-button.less';
|
||||||
@import './editor/figure-modal.less';
|
@import './editor/figure-modal.less';
|
||||||
@import './editor/table-generator.less';
|
|
||||||
|
|
||||||
@ui-layout-toggler-def-height: 50px;
|
@ui-layout-toggler-def-height: 50px;
|
||||||
@ui-resizer-size: 7px;
|
@ui-resizer-size: 7px;
|
||||||
|
|
|
@ -1,397 +0,0 @@
|
||||||
@table-generator-active-border-color: #666;
|
|
||||||
@table-generator-inactive-border-color: #dedede;
|
|
||||||
@table-generator-focus-border-width: 2px;
|
|
||||||
@table-generator-focus-negative-border-width: -2px;
|
|
||||||
@table-generator-focus-border-color: #97b6e5;
|
|
||||||
@table-generator-selector-hover-color: #3265b2;
|
|
||||||
@table-generator-selector-handle-buffer: 12px;
|
|
||||||
@table-generator-toolbar-shadow-color: #1e253029;
|
|
||||||
@table-generator-toolbar-background: #fff;
|
|
||||||
@table-generator-inactive-border-width: 1px;
|
|
||||||
@table-generator-active-border-width: 1px;
|
|
||||||
|
|
||||||
.table-generator-cell {
|
|
||||||
border: @table-generator-inactive-border-width dashed
|
|
||||||
@table-generator-inactive-border-color;
|
|
||||||
min-width: 40px;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-cell-border-left {
|
|
||||||
border-left-style: solid;
|
|
||||||
border-left-color: @table-generator-active-border-color;
|
|
||||||
border-left-width: @table-generator-active-border-width;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-cell-border-right {
|
|
||||||
border-right-style: solid;
|
|
||||||
border-right-color: @table-generator-active-border-color;
|
|
||||||
border-right-width: @table-generator-active-border-width;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-row-border-top {
|
|
||||||
border-top-style: solid;
|
|
||||||
border-top-color: @table-generator-active-border-color;
|
|
||||||
border-top-width: @table-generator-active-border-width;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-row-border-bottom {
|
|
||||||
border-bottom-style: solid;
|
|
||||||
border-bottom-color: @table-generator-active-border-color;
|
|
||||||
border-bottom-width: @table-generator-active-border-width;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-cell.selected {
|
|
||||||
background-color: @blue-10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-cell:focus-visible {
|
|
||||||
outline: 2px dotted @table-generator-focus-border-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-cell {
|
|
||||||
&.selection-edge-top {
|
|
||||||
--shadow-top: 0 @table-generator-focus-negative-border-width 0
|
|
||||||
@table-generator-focus-border-color;
|
|
||||||
}
|
|
||||||
&.selection-edge-bottom {
|
|
||||||
--shadow-bottom: 0 @table-generator-focus-border-width 0
|
|
||||||
@table-generator-focus-border-color;
|
|
||||||
}
|
|
||||||
&.selection-edge-left {
|
|
||||||
--shadow-left: @table-generator-focus-negative-border-width 0 0
|
|
||||||
@table-generator-focus-border-color;
|
|
||||||
}
|
|
||||||
&.selection-edge-right {
|
|
||||||
--shadow-right: @table-generator-focus-border-width 0 0
|
|
||||||
@table-generator-focus-border-color;
|
|
||||||
}
|
|
||||||
box-shadow: var(--shadow-top, 0 0 0 transparent),
|
|
||||||
var(--shadow-bottom, 0 0 0 transparent),
|
|
||||||
var(--shadow-left, 0 0 0 transparent),
|
|
||||||
var(--shadow-right, 0 0 0 transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-table {
|
|
||||||
table-layout: fixed;
|
|
||||||
max-width: 80%;
|
|
||||||
margin: 0 auto;
|
|
||||||
cursor: default;
|
|
||||||
|
|
||||||
& td {
|
|
||||||
padding: 0 0.25em;
|
|
||||||
max-width: 200px;
|
|
||||||
|
|
||||||
&.alignment-left {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
&.alignment-right {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
&.alignment-center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
&.alignment-paragraph {
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-selector-cell {
|
|
||||||
padding: 0;
|
|
||||||
border: none !important;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&.row-selector {
|
|
||||||
width: @table-generator-selector-handle-buffer + 8px;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
width: 4px;
|
|
||||||
height: calc(100% - 8px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.column-selector {
|
|
||||||
height: @table-generator-selector-handle-buffer + 8px;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
width: calc(100% - 8px);
|
|
||||||
height: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 4px;
|
|
||||||
right: 4px;
|
|
||||||
width: calc(100% - 8px);
|
|
||||||
height: calc(100% - 8px);
|
|
||||||
background-color: @neutral-30;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover::after {
|
|
||||||
background-color: @neutral-40;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.fully-selected::after {
|
|
||||||
background-color: @table-generator-selector-hover-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-floating-toolbar {
|
|
||||||
position: absolute;
|
|
||||||
top: -36px;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: 0 auto;
|
|
||||||
z-index: 1;
|
|
||||||
border-radius: 4px;
|
|
||||||
width: max-content;
|
|
||||||
background-color: @table-generator-toolbar-background;
|
|
||||||
box-shadow: 0px 2px 4px 0px @table-generator-toolbar-shadow-color;
|
|
||||||
padding: 4px;
|
|
||||||
height: 40px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-toolbar-button {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
line-height: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
color: @neutral-70;
|
|
||||||
text-align: center;
|
|
||||||
padding: 4px;
|
|
||||||
|
|
||||||
&:not(:first-child) {
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
&:not(:last-child) {
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > span {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
background-color: rgba(47, 58, 76, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active,
|
|
||||||
&.active {
|
|
||||||
background-color: rgba(47, 58, 76, 0.16);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active,
|
|
||||||
&.active {
|
|
||||||
color: inherit;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[aria-disabled='true'] {
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active,
|
|
||||||
&.active {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
color: @neutral-40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-button-group {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
line-height: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
&:not(:first-child) {
|
|
||||||
border-left: 1px solid @neutral-20;
|
|
||||||
padding-left: 8px;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-button-menu-popover {
|
|
||||||
.popover-content {
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
.list-group {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
& > .arrow {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-cell-input {
|
|
||||||
max-width: calc(200px - 0.5em);
|
|
||||||
width: 100%;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 1px solid @table-generator-toolbar-shadow-color;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-border-options-coming-soon {
|
|
||||||
display: flex;
|
|
||||||
margin: 4px;
|
|
||||||
font-size: 12px;
|
|
||||||
background: @neutral-10;
|
|
||||||
color: @neutral-70;
|
|
||||||
padding: 8px;
|
|
||||||
gap: 6px;
|
|
||||||
align-items: flex-start;
|
|
||||||
max-width: 240px;
|
|
||||||
|
|
||||||
& .info-icon {
|
|
||||||
flex: 0 0 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-toolbar-dropdown-toggle {
|
|
||||||
border: 1px solid @neutral-60;
|
|
||||||
box-shadow: none;
|
|
||||||
background: transparent;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: inherit;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 6px 8px;
|
|
||||||
gap: 8px;
|
|
||||||
min-width: 120px;
|
|
||||||
font-size: 14px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
font-family: @font-family-sans-serif;
|
|
||||||
|
|
||||||
&:not(:first-child) {
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[aria-disabled='true'] {
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
color: @neutral-40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-toolbar-dropdown-popover {
|
|
||||||
max-width: 300px;
|
|
||||||
|
|
||||||
.popover-content {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .arrow {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-toolbar-dropdown-menu {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-width: 200px;
|
|
||||||
|
|
||||||
& > button {
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
background: transparent;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: inherit;
|
|
||||||
border-radius: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
column-gap: 8px;
|
|
||||||
align-self: stretch;
|
|
||||||
padding: 12px 8px;
|
|
||||||
font-family: @font-family-sans-serif;
|
|
||||||
|
|
||||||
.table-generator-button-label {
|
|
||||||
align-self: stretch;
|
|
||||||
flex: 1 0 auto;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
background-color: rgba(47, 58, 76, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active,
|
|
||||||
&.active {
|
|
||||||
background-color: rgba(47, 58, 76, 0.16);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active,
|
|
||||||
&.active {
|
|
||||||
color: inherit;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[aria-disabled='true'] {
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active,
|
|
||||||
&.active {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
color: @neutral-40;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > hr {
|
|
||||||
background: @neutral-20;
|
|
||||||
margin: 2px 8px;
|
|
||||||
display: block;
|
|
||||||
box-sizing: content-box;
|
|
||||||
border: 0;
|
|
||||||
height: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-error {
|
|
||||||
background: linear-gradient(0deg, #f9f1f1, #f9f1f1),
|
|
||||||
linear-gradient(0deg, #f5beba, #f5beba);
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
color: black;
|
|
||||||
border: 1px solid #f5beba;
|
|
||||||
font-family: @font-family-sans-serif;
|
|
||||||
margin-bottom: 0;
|
|
||||||
.table-generator-error-message {
|
|
||||||
flex: 1 0 auto;
|
|
||||||
}
|
|
||||||
.table-generator-error-icon {
|
|
||||||
color: #b83a33;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-generator-filler-row {
|
|
||||||
border: none !important;
|
|
||||||
td {
|
|
||||||
min-width: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,4 +23,14 @@
|
||||||
|
|
||||||
--toolbar-btn-color: @toolbar-btn-color;
|
--toolbar-btn-color: @toolbar-btn-color;
|
||||||
--editor-toolbar-bg: @editor-toolbar-bg;
|
--editor-toolbar-bg: @editor-toolbar-bg;
|
||||||
|
|
||||||
|
--neutral-10: @neutral-10;
|
||||||
|
--neutral-20: @neutral-20;
|
||||||
|
--neutral-30: @neutral-30;
|
||||||
|
--neutral-40: @neutral-40;
|
||||||
|
--neutral-60: @neutral-60;
|
||||||
|
--neutral-70: @neutral-70;
|
||||||
|
--neutral-80: @neutral-80;
|
||||||
|
--neutral-90: @neutral-90;
|
||||||
|
--blue-10: @blue-10;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue