mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #21477 from overleaf/ii-bs5-table-generator
[web] BS5 table generator GitOrigin-RevId: 3fe10c05fa36f026c47ff4f54b15f5d76f7c509e
This commit is contained in:
parent
ba7d11d854
commit
1033e73844
12 changed files with 238 additions and 224 deletions
|
@ -1,9 +1,8 @@
|
||||||
import MaterialIcon from '@/shared/components/material-icon'
|
import MaterialIcon from '@/shared/components/material-icon'
|
||||||
import { WidthSelection } from './toolbar/column-width-modal/column-width'
|
import { WidthSelection } from './toolbar/column-width-modal/column-width'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { Button } from 'react-bootstrap'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Tooltip from '@/shared/components/tooltip'
|
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||||
import { useSelectionContext } from './contexts/selection-context'
|
import { useSelectionContext } from './contexts/selection-context'
|
||||||
|
|
||||||
function roundIfNeeded(width: number) {
|
function roundIfNeeded(width: number) {
|
||||||
|
@ -32,7 +31,7 @@ export const ColumnSizeIndicator = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<OLTooltip
|
||||||
id="tooltip-column-width-button"
|
id="tooltip-column-width-button"
|
||||||
description={
|
description={
|
||||||
unit === 'custom'
|
unit === 'custom'
|
||||||
|
@ -43,9 +42,8 @@ export const ColumnSizeIndicator = ({
|
||||||
}
|
}
|
||||||
overlayProps={{ delay: 0, placement: 'bottom' }}
|
overlayProps={{ delay: 0, placement: 'bottom' }}
|
||||||
>
|
>
|
||||||
<Button
|
<button
|
||||||
bsStyle={null}
|
className="btn table-generator-column-indicator-button"
|
||||||
className="table-generator-column-indicator-button"
|
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
<MaterialIcon
|
<MaterialIcon
|
||||||
|
@ -55,7 +53,7 @@ export const ColumnSizeIndicator = ({
|
||||||
<span className="table-generator-column-indicator-label">
|
<span className="table-generator-column-indicator-label">
|
||||||
{formattedWidth}
|
{formattedWidth}
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</button>
|
||||||
</Tooltip>
|
</OLTooltip>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import { Button, Modal } from 'react-bootstrap'
|
import OLModal, {
|
||||||
import AccessibleModal from '../../../../shared/components/accessible-modal'
|
OLModalBody,
|
||||||
|
OLModalFooter,
|
||||||
|
OLModalHeader,
|
||||||
|
OLModalTitle,
|
||||||
|
} from '@/features/ui/components/ol/ol-modal'
|
||||||
|
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||||
import { useTabularContext } from './contexts/tabular-context'
|
import { useTabularContext } from './contexts/tabular-context'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
@ -9,15 +14,15 @@ export const TableGeneratorHelpModal = () => {
|
||||||
if (!helpShown) return null
|
if (!helpShown) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AccessibleModal
|
<OLModal
|
||||||
show={helpShown}
|
show={helpShown}
|
||||||
onHide={hideHelp}
|
onHide={hideHelp}
|
||||||
className="table-generator-help-modal"
|
className="table-generator-help-modal"
|
||||||
>
|
>
|
||||||
<Modal.Header closeButton>
|
<OLModalHeader closeButton>
|
||||||
<Modal.Title>{t('help')}</Modal.Title>
|
<OLModalTitle>{t('help')}</OLModalTitle>
|
||||||
</Modal.Header>
|
</OLModalHeader>
|
||||||
<Modal.Body>
|
<OLModalBody>
|
||||||
<p>
|
<p>
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey="this_tool_helps_you_insert_simple_tables_into_your_project_without_writing_latex_code_give_feedback"
|
i18nKey="this_tool_helps_you_insert_simple_tables_into_your_project_without_writing_latex_code_give_feedback"
|
||||||
|
@ -83,10 +88,12 @@ export const TableGeneratorHelpModal = () => {
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</Modal.Body>
|
</OLModalBody>
|
||||||
<Modal.Footer>
|
<OLModalFooter>
|
||||||
<Button onClick={hideHelp}>{t('close')}</Button>
|
<OLButton variant="secondary" onClick={hideHelp}>
|
||||||
</Modal.Footer>
|
{t('close')}
|
||||||
</AccessibleModal>
|
</OLButton>
|
||||||
|
</OLModalFooter>
|
||||||
|
</OLModal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import {
|
||||||
} from './contexts/editing-context'
|
} from './contexts/editing-context'
|
||||||
import { EditorView } from '@codemirror/view'
|
import { EditorView } from '@codemirror/view'
|
||||||
import { ErrorBoundary } from 'react-error-boundary'
|
import { ErrorBoundary } from 'react-error-boundary'
|
||||||
import { Alert, Button } from 'react-bootstrap'
|
|
||||||
import { EditorSelection } from '@codemirror/state'
|
import { EditorSelection } from '@codemirror/state'
|
||||||
import {
|
import {
|
||||||
CodeMirrorViewContext,
|
CodeMirrorViewContext,
|
||||||
|
@ -22,13 +21,14 @@ import {
|
||||||
} from '../codemirror-context'
|
} from '../codemirror-context'
|
||||||
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 { BorderTheme } from './toolbar/commands'
|
import { BorderTheme } from './toolbar/commands'
|
||||||
import { TableGeneratorHelpModal } from './help-modal'
|
import { TableGeneratorHelpModal } from './help-modal'
|
||||||
import { SplitTestProvider } from '../../../../shared/context/split-test-context'
|
import { SplitTestProvider } from '../../../../shared/context/split-test-context'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { ColumnWidthModal } from './toolbar/column-width-modal/modal'
|
import { ColumnWidthModal } from './toolbar/column-width-modal/modal'
|
||||||
import { WidthSelection } from './toolbar/column-width-modal/column-width'
|
import { WidthSelection } from './toolbar/column-width-modal/column-width'
|
||||||
|
import Notification from '@/shared/components/notification'
|
||||||
|
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||||
|
|
||||||
export type ColumnDefinition = {
|
export type ColumnDefinition = {
|
||||||
alignment: 'left' | 'center' | 'right' | 'paragraph'
|
alignment: 'left' | 'center' | 'right' | 'paragraph'
|
||||||
|
@ -198,35 +198,40 @@ export const TableRenderingError: FC<{
|
||||||
codePosition?: number
|
codePosition?: number
|
||||||
}> = ({ view, codePosition }) => {
|
}> = ({ view, codePosition }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert className="table-generator-error">
|
<Notification
|
||||||
<span className="table-generator-error-icon">
|
type="info"
|
||||||
<Icon type="exclamation-circle" />
|
content={
|
||||||
</span>
|
<>
|
||||||
<div className="table-generator-error-message">
|
<p>
|
||||||
<p className="table-generator-error-message-header">
|
<strong>
|
||||||
{t('sorry_your_table_cant_be_displayed_at_the_moment')}
|
{t('sorry_your_table_cant_be_displayed_at_the_moment')}
|
||||||
</p>
|
</strong>
|
||||||
<p>
|
</p>
|
||||||
{t(
|
<p>
|
||||||
'this_could_be_because_we_cant_support_some_elements_of_the_table'
|
{t(
|
||||||
)}
|
'this_could_be_because_we_cant_support_some_elements_of_the_table'
|
||||||
</p>
|
)}
|
||||||
</div>
|
</p>
|
||||||
{codePosition !== undefined && (
|
</>
|
||||||
<Button
|
}
|
||||||
bsStyle={null}
|
action={
|
||||||
className="btn-secondary table-generator-error-show-code-button"
|
codePosition !== undefined ? (
|
||||||
onClick={() =>
|
<OLButton
|
||||||
view.dispatch({
|
variant="secondary"
|
||||||
selection: EditorSelection.cursor(codePosition),
|
onClick={() =>
|
||||||
})
|
view.dispatch({
|
||||||
}
|
selection: EditorSelection.cursor(codePosition),
|
||||||
>
|
})
|
||||||
{t('view_code')}
|
}
|
||||||
</Button>
|
size="sm"
|
||||||
)}
|
>
|
||||||
</Alert>
|
{t('view_code')}
|
||||||
|
</OLButton>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import AccessibleModal from '@/shared/components/accessible-modal'
|
|
||||||
import { Button, Modal, Form, FormGroup } from 'react-bootstrap'
|
|
||||||
import { useTabularContext } from '../../contexts/tabular-context'
|
import { useTabularContext } from '../../contexts/tabular-context'
|
||||||
import { Select } from '@/shared/components/select'
|
import { Select } from '@/shared/components/select'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
|
@ -18,8 +16,24 @@ import { setColumnWidth } from '../commands'
|
||||||
import { UNITS, WidthSelection, WidthUnit } from './column-width'
|
import { UNITS, WidthSelection, WidthUnit } from './column-width'
|
||||||
import { useCodeMirrorViewContext } from '../../../codemirror-context'
|
import { useCodeMirrorViewContext } from '../../../codemirror-context'
|
||||||
import { CopyToClipboard } from '@/shared/components/copy-to-clipboard'
|
import { CopyToClipboard } from '@/shared/components/copy-to-clipboard'
|
||||||
import Tooltip from '@/shared/components/tooltip'
|
|
||||||
import Icon from '@/shared/components/icon'
|
import Icon from '@/shared/components/icon'
|
||||||
|
import OLModal, {
|
||||||
|
OLModalBody,
|
||||||
|
OLModalFooter,
|
||||||
|
OLModalHeader,
|
||||||
|
OLModalTitle,
|
||||||
|
} from '@/features/ui/components/ol/ol-modal'
|
||||||
|
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||||
|
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||||
|
import OLFormGroup from '@/features/ui/components/ol/ol-form-group'
|
||||||
|
import OLFormLabel from '@/features/ui/components/ol/ol-form-label'
|
||||||
|
import OLFormControl from '@/features/ui/components/ol/ol-form-control'
|
||||||
|
import OLCol from '@/features/ui/components/ol/ol-col'
|
||||||
|
import OLRow from '@/features/ui/components/ol/ol-row'
|
||||||
|
import OLForm from '@/features/ui/components/ol/ol-form'
|
||||||
|
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||||
|
import MaterialIcon from '@/shared/components/material-icon'
|
||||||
|
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||||
|
|
||||||
type UnitDescription = { label: string; tooltip?: string } | undefined
|
type UnitDescription = { label: string; tooltip?: string } | undefined
|
||||||
|
|
||||||
|
@ -93,7 +107,7 @@ const ColumnWidthModalBody = () => {
|
||||||
}
|
}
|
||||||
}, [columnWidthModalShown, selection, table])
|
}, [columnWidthModalShown, selection, table])
|
||||||
|
|
||||||
const onSubmit: FormEventHandler<Form> = useCallback(
|
const onSubmit: FormEventHandler<HTMLFormElement> = useCallback(
|
||||||
e => {
|
e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (selection && currentUnit) {
|
if (selection && currentUnit) {
|
||||||
|
@ -121,60 +135,67 @@ const ColumnWidthModalBody = () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AccessibleModal
|
<OLModal
|
||||||
show={columnWidthModalShown}
|
show={columnWidthModalShown}
|
||||||
onHide={closeColumnWidthModal}
|
onHide={closeColumnWidthModal}
|
||||||
className="table-generator-width-modal"
|
className="table-generator-width-modal"
|
||||||
>
|
>
|
||||||
<Form onSubmit={onSubmit}>
|
<OLModalHeader closeButton>
|
||||||
<Modal.Header closeButton>
|
<OLModalTitle>{t('set_column_width')}</OLModalTitle>
|
||||||
<Modal.Title>{t('set_column_width')}</Modal.Title>
|
</OLModalHeader>
|
||||||
</Modal.Header>
|
<OLModalBody>
|
||||||
<Modal.Body>
|
<OLForm id="table-generator-width-form" onSubmit={onSubmit}>
|
||||||
<div className="clearfix">
|
<OLRow className={bsVersion({ bs5: 'g-3' })}>
|
||||||
<FormGroup className="col-md-8 p-0 mb-0">
|
<OLCol lg={8}>
|
||||||
<label
|
<OLFormGroup
|
||||||
className="table-generator-width-label"
|
controlId="column-width-modal-width"
|
||||||
htmlFor="column-width-modal-width"
|
className="mb-0"
|
||||||
>
|
>
|
||||||
{t('column_width')}
|
<OLFormLabel>{t('column_width')}</OLFormLabel>
|
||||||
</label>
|
<OLFormControl
|
||||||
<input
|
value={currentWidth}
|
||||||
id="column-width-modal-width"
|
required
|
||||||
value={currentWidth}
|
onChange={e => setCurrentWidth(e.target.value)}
|
||||||
required
|
type={currentUnit === 'custom' ? 'text' : 'number'}
|
||||||
onChange={e => setCurrentWidth(e.target.value)}
|
ref={inputRef}
|
||||||
type={currentUnit === 'custom' ? 'text' : 'number'}
|
/>
|
||||||
className="form-control"
|
</OLFormGroup>
|
||||||
ref={inputRef}
|
</OLCol>
|
||||||
/>
|
<OLCol lg={4}>
|
||||||
</FormGroup>
|
<OLFormGroup className="mb-0">
|
||||||
<FormGroup className="col-md-4 mb-0">
|
<Select
|
||||||
<Select
|
label={
|
||||||
label={
|
<>
|
||||||
<>
|
<span className="sr-only">{t('length_unit')}</span>
|
||||||
<span className="sr-only">{t('length_unit')}</span>
|
</>
|
||||||
</>
|
}
|
||||||
}
|
items={UNITS}
|
||||||
items={UNITS}
|
itemToKey={x => x ?? ''}
|
||||||
itemToKey={x => x ?? ''}
|
itemToString={x => (x === 'custom' ? t('custom') : (x ?? ''))}
|
||||||
itemToString={x => (x === 'custom' ? t('custom') : (x ?? ''))}
|
onSelectedItemChanged={item => setCurrentUnit(item)}
|
||||||
onSelectedItemChanged={item => setCurrentUnit(item)}
|
defaultItem={currentUnit}
|
||||||
defaultItem={currentUnit}
|
/>
|
||||||
/>
|
</OLFormGroup>
|
||||||
</FormGroup>
|
</OLCol>
|
||||||
</div>
|
</OLRow>
|
||||||
{unitHelp && (
|
{unitHelp && (
|
||||||
<p className="my-1">
|
<p className="my-1">
|
||||||
{unitHelp.label}{' '}
|
{unitHelp.label}{' '}
|
||||||
{unitHelp.tooltip && (
|
{unitHelp.tooltip && (
|
||||||
<Tooltip
|
<OLTooltip
|
||||||
id="table-generator-unit-tooltip"
|
id="table-generator-unit-tooltip"
|
||||||
description={unitHelp.tooltip}
|
description={unitHelp.tooltip}
|
||||||
overlayProps={{ delay: 0, placement: 'top' }}
|
overlayProps={{ delay: 0, placement: 'top' }}
|
||||||
>
|
>
|
||||||
<Icon type="question-circle" fw />
|
<span>
|
||||||
</Tooltip>
|
<BootstrapVersionSwitcher
|
||||||
|
bs3={<Icon type="question-circle" />}
|
||||||
|
bs5={
|
||||||
|
<MaterialIcon type="help" className="align-middle" />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</OLTooltip>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
@ -196,22 +217,25 @@ const ColumnWidthModalBody = () => {
|
||||||
tooltipId="table-generator-array-copy"
|
tooltipId="table-generator-array-copy"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Modal.Body>
|
</OLForm>
|
||||||
<Modal.Footer>
|
</OLModalBody>
|
||||||
<Button
|
<OLModalFooter>
|
||||||
bsStyle={null}
|
<OLButton
|
||||||
className="btn-secondary"
|
variant="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
closeColumnWidthModal()
|
closeColumnWidthModal()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('cancel')}
|
{t('cancel')}
|
||||||
</Button>
|
</OLButton>
|
||||||
<Button bsStyle={null} className="btn-primary" type="submit">
|
<OLButton
|
||||||
{t('ok')}
|
variant="primary"
|
||||||
</Button>
|
form="table-generator-width-form"
|
||||||
</Modal.Footer>
|
type="submit"
|
||||||
</Form>
|
>
|
||||||
</AccessibleModal>
|
{t('ok')}
|
||||||
|
</OLButton>
|
||||||
|
</OLModalFooter>
|
||||||
|
</OLModal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import { FC, memo, useRef } from 'react'
|
import { FC, memo, useRef } from 'react'
|
||||||
import useDropdown from '../../../../../shared/hooks/use-dropdown'
|
import useDropdown from '../../../../../shared/hooks/use-dropdown'
|
||||||
import { ListGroup, Overlay, Popover } from 'react-bootstrap'
|
import OLListGroup from '@/features/ui/components/ol/ol-list-group'
|
||||||
import Tooltip from '../../../../../shared/components/tooltip'
|
import OLOverlay from '@/features/ui/components/ol/ol-overlay'
|
||||||
|
import OLPopover from '@/features/ui/components/ol/ol-popover'
|
||||||
|
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||||
import MaterialIcon from '../../../../../shared/components/material-icon'
|
import MaterialIcon from '../../../../../shared/components/material-icon'
|
||||||
import { useTabularContext } from '../contexts/tabular-context'
|
import { useTabularContext } from '../contexts/tabular-context'
|
||||||
|
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||||
|
|
||||||
export const ToolbarButtonMenu: FC<{
|
export const ToolbarButtonMenu: FC<{
|
||||||
id: string
|
id: string
|
||||||
|
@ -45,36 +48,37 @@ export const ToolbarButtonMenu: FC<{
|
||||||
)
|
)
|
||||||
|
|
||||||
const overlay = tableContainerRef.current && (
|
const overlay = tableContainerRef.current && (
|
||||||
<Overlay
|
<OLOverlay
|
||||||
show={open}
|
show={open}
|
||||||
target={target.current}
|
target={target.current}
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
container={tableContainerRef.current}
|
container={tableContainerRef.current}
|
||||||
containerPadding={0}
|
containerPadding={0}
|
||||||
animation
|
transition
|
||||||
rootClose
|
rootClose
|
||||||
onHide={() => onToggle(false)}
|
onHide={() => onToggle(false)}
|
||||||
>
|
>
|
||||||
<Popover
|
<OLPopover
|
||||||
id={`${id}-menu`}
|
id={`${id}-menu`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className="table-generator-button-menu-popover"
|
className="table-generator-button-menu-popover"
|
||||||
>
|
>
|
||||||
<ListGroup
|
<OLListGroup
|
||||||
role="menu"
|
role="menu"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onToggle(false)
|
onToggle(false)
|
||||||
}}
|
}}
|
||||||
|
className={bsVersion({ bs5: 'd-block' })}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</ListGroup>
|
</OLListGroup>
|
||||||
</Popover>
|
</OLPopover>
|
||||||
</Overlay>
|
</OLOverlay>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip
|
<OLTooltip
|
||||||
hidden={open}
|
hidden={open}
|
||||||
id={id}
|
id={id}
|
||||||
description={
|
description={
|
||||||
|
@ -83,7 +87,7 @@ export const ToolbarButtonMenu: FC<{
|
||||||
overlayProps={{ placement: 'bottom' }}
|
overlayProps={{ placement: 'bottom' }}
|
||||||
>
|
>
|
||||||
{button}
|
{button}
|
||||||
</Tooltip>
|
</OLTooltip>
|
||||||
{overlay}
|
{overlay}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { EditorView } from '@codemirror/view'
|
import { EditorView } from '@codemirror/view'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { memo, useCallback } from 'react'
|
import { memo, useCallback } from 'react'
|
||||||
import Tooltip from '../../../../../shared/components/tooltip'
|
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||||
import MaterialIcon from '../../../../../shared/components/material-icon'
|
import MaterialIcon from '../../../../../shared/components/material-icon'
|
||||||
import { useCodeMirrorViewContext } from '../../codemirror-context'
|
import { useCodeMirrorViewContext } from '../../codemirror-context'
|
||||||
import { emitTableGeneratorEvent } from '../analytics'
|
import { emitTableGeneratorEvent } from '../analytics'
|
||||||
|
@ -64,12 +64,12 @@ export const ToolbarButton = memo<{
|
||||||
disabled && disabledLabel ? <div>{disabledLabel}</div> : <div>{label}</div>
|
disabled && disabledLabel ? <div>{disabledLabel}</div> : <div>{label}</div>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<OLTooltip
|
||||||
id={id}
|
id={id}
|
||||||
description={description}
|
description={description}
|
||||||
overlayProps={{ placement: 'bottom' }}
|
overlayProps={{ placement: 'bottom' }}
|
||||||
>
|
>
|
||||||
{button}
|
{button}
|
||||||
</Tooltip>
|
</OLTooltip>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { ButtonHTMLAttributes, FC, useCallback, useRef } from 'react'
|
import { ButtonHTMLAttributes, FC, useCallback, useRef } from 'react'
|
||||||
import useDropdown from '../../../../../shared/hooks/use-dropdown'
|
import useDropdown from '../../../../../shared/hooks/use-dropdown'
|
||||||
import { Overlay, Popover } from 'react-bootstrap'
|
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||||
|
import OLOverlay from '@/features/ui/components/ol/ol-overlay'
|
||||||
|
import OLPopover from '@/features/ui/components/ol/ol-popover'
|
||||||
import MaterialIcon from '../../../../../shared/components/material-icon'
|
import MaterialIcon from '../../../../../shared/components/material-icon'
|
||||||
import Tooltip from '../../../../../shared/components/tooltip'
|
|
||||||
import { useTabularContext } from '../contexts/tabular-context'
|
import { useTabularContext } from '../contexts/tabular-context'
|
||||||
import { emitTableGeneratorEvent } from '../analytics'
|
import { emitTableGeneratorEvent } from '../analytics'
|
||||||
import { useCodeMirrorViewContext } from '../../codemirror-context'
|
import { useCodeMirrorViewContext } from '../../codemirror-context'
|
||||||
|
@ -55,17 +56,17 @@ export const ToolbarDropdown: FC<{
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
const overlay = tabularRef.current && (
|
const overlay = tabularRef.current && (
|
||||||
<Overlay
|
<OLOverlay
|
||||||
show={open}
|
show={open}
|
||||||
target={toggleButtonRef.current ?? undefined}
|
target={toggleButtonRef.current}
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
container={tabularRef.current}
|
container={tabularRef.current}
|
||||||
animation
|
transition
|
||||||
rootClose
|
rootClose
|
||||||
containerPadding={0}
|
containerPadding={0}
|
||||||
onHide={() => onToggle(false)}
|
onHide={() => onToggle(false)}
|
||||||
>
|
>
|
||||||
<Popover
|
<OLPopover
|
||||||
id={`${id}-popover`}
|
id={`${id}-popover`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className="table-generator-toolbar-dropdown-popover"
|
className="table-generator-toolbar-dropdown-popover"
|
||||||
|
@ -82,21 +83,21 @@ export const ToolbarDropdown: FC<{
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</Popover>
|
</OLPopover>
|
||||||
</Overlay>
|
</OLOverlay>
|
||||||
)
|
)
|
||||||
|
|
||||||
if (tooltip || (disabled && disabledTooltip)) {
|
if (tooltip || (disabled && disabledTooltip)) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip
|
<OLTooltip
|
||||||
hidden={open}
|
hidden={open}
|
||||||
id={id}
|
id={id}
|
||||||
description={disabled && disabledTooltip ? disabledTooltip : tooltip}
|
description={disabled && disabledTooltip ? disabledTooltip : tooltip}
|
||||||
overlayProps={{ placement: 'bottom' }}
|
overlayProps={{ placement: 'bottom' }}
|
||||||
>
|
>
|
||||||
{button}
|
{button}
|
||||||
</Tooltip>
|
</OLTooltip>
|
||||||
{overlay}
|
{overlay}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { EditorView } from '@codemirror/view'
|
import { EditorView } from '@codemirror/view'
|
||||||
|
import { isBootstrap5 } from '@/features/utils/bootstrap-5'
|
||||||
|
|
||||||
export const tableGeneratorTheme = EditorView.baseTheme({
|
export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
'&dark .table-generator': {
|
'&dark .table-generator': {
|
||||||
|
@ -309,14 +310,14 @@ export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
|
|
||||||
'.table-generator-button-menu-popover': {
|
'.table-generator-button-menu-popover': {
|
||||||
'background-color': 'var(--table-generator-toolbar-background) !important',
|
'background-color': 'var(--table-generator-toolbar-background) !important',
|
||||||
'& .popover-content': {
|
'& .popover-content, & .popover-body': {
|
||||||
padding: '4px',
|
padding: '4px',
|
||||||
},
|
},
|
||||||
'& .list-group': {
|
'& .list-group': {
|
||||||
margin: '0',
|
margin: '0',
|
||||||
padding: '0',
|
padding: '0',
|
||||||
},
|
},
|
||||||
'& > .arrow': {
|
'& > .arrow, & > .popover-arrow': {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -348,7 +349,7 @@ export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
gap: '6px',
|
gap: '6px',
|
||||||
'align-items': 'flex-start',
|
'align-items': 'flex-start',
|
||||||
'max-width': '240px',
|
'max-width': '240px',
|
||||||
'font-family': 'Lato',
|
'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato',
|
||||||
|
|
||||||
'& .info-icon': {
|
'& .info-icon': {
|
||||||
flex: ' 0 0 24px',
|
flex: ' 0 0 24px',
|
||||||
|
@ -369,7 +370,7 @@ export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
'align-items': 'center',
|
'align-items': 'center',
|
||||||
'justify-content': 'space-between',
|
'justify-content': 'space-between',
|
||||||
'font-family': 'Lato',
|
'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato',
|
||||||
height: '36px',
|
height: '36px',
|
||||||
|
|
||||||
'&:not(:first-child)': {
|
'&:not(:first-child)': {
|
||||||
|
@ -387,11 +388,11 @@ export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
'max-width': '300px',
|
'max-width': '300px',
|
||||||
background: 'var(--table-generator-toolbar-background) !important',
|
background: 'var(--table-generator-toolbar-background) !important',
|
||||||
|
|
||||||
'& .popover-content': {
|
'& .popover-content, & .popover-body': {
|
||||||
padding: '0',
|
padding: '0',
|
||||||
},
|
},
|
||||||
|
|
||||||
'& > .arrow': {
|
'& > .arrow, & > .popover-arrow': {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -416,7 +417,7 @@ export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
'column-gap': '8px',
|
'column-gap': '8px',
|
||||||
'align-self': 'stretch',
|
'align-self': 'stretch',
|
||||||
padding: '12px 8px',
|
padding: '12px 8px',
|
||||||
'font-family': 'Lato',
|
'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato',
|
||||||
|
|
||||||
'& .table-generator-button-label': {
|
'& .table-generator-button-label': {
|
||||||
'align-self': 'stretch',
|
'align-self': 'stretch',
|
||||||
|
@ -482,32 +483,9 @@ export const tableGeneratorTheme = EditorView.baseTheme({
|
||||||
'.ol-cm-environment-table.table-generator-error-container, .ol-cm-environment-table.ol-cm-tabular':
|
'.ol-cm-environment-table.table-generator-error-container, .ol-cm-environment-table.ol-cm-tabular':
|
||||||
{
|
{
|
||||||
background: 'rgba(125, 125, 125, 0.05)',
|
background: 'rgba(125, 125, 125, 0.05)',
|
||||||
|
'font-family': isBootstrap5() ? 'var(--bs-body-font-family)' : 'Lato',
|
||||||
},
|
},
|
||||||
|
|
||||||
'.table-generator-error': {
|
|
||||||
background: 'var(--table-generator-error-background)',
|
|
||||||
display: 'flex',
|
|
||||||
'justify-content': 'space-between',
|
|
||||||
color: 'var(--table-generator-error-color)',
|
|
||||||
border: '1px solid var(--table-generator-error-border-color)',
|
|
||||||
'font-family': 'Lato',
|
|
||||||
margin: '0 16px 0 16px',
|
|
||||||
'& .table-generator-error-message': {
|
|
||||||
flex: '1 1 auto',
|
|
||||||
},
|
|
||||||
'& .table-generator-error-message-header': {
|
|
||||||
fontWeight: 'bold',
|
|
||||||
marginBottom: '2px',
|
|
||||||
},
|
|
||||||
'& .table-generator-error-show-code-button': {
|
|
||||||
alignSelf: 'baseline',
|
|
||||||
},
|
|
||||||
'& .table-generator-error-icon': {
|
|
||||||
color: '#3265B2',
|
|
||||||
'margin-right': '12px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
'.table-generator-filler-row': {
|
'.table-generator-filler-row': {
|
||||||
border: 'none !important',
|
border: 'none !important',
|
||||||
'& td': {
|
'& td': {
|
||||||
|
|
|
@ -10,28 +10,34 @@ export class TableRenderingErrorWidget extends WidgetType {
|
||||||
|
|
||||||
toDOM(view: EditorView): HTMLElement {
|
toDOM(view: EditorView): HTMLElement {
|
||||||
const warning = document.createElement('div')
|
const warning = document.createElement('div')
|
||||||
warning.classList.add('table-generator-error', 'alert')
|
warning.classList.add('notification', 'notification-type-info')
|
||||||
warning.role = 'alert'
|
warning.role = 'alert'
|
||||||
const icon = document.createElement('span')
|
const icon = document.createElement('div')
|
||||||
icon.classList.add('table-generator-error-icon')
|
icon.classList.add('notification-icon')
|
||||||
const iconType = document.createElement('i')
|
const iconType = document.createElement('span')
|
||||||
iconType.classList.add('fa', 'fa-info-circle')
|
iconType.classList.add('material-symbols')
|
||||||
|
iconType.setAttribute('aria-hidden', 'true')
|
||||||
|
iconType.textContent = 'info'
|
||||||
icon.appendChild(iconType)
|
icon.appendChild(iconType)
|
||||||
warning.appendChild(icon)
|
warning.appendChild(icon)
|
||||||
|
const messageWrapper = document.createElement('div')
|
||||||
|
messageWrapper.classList.add('notification-content-and-cta')
|
||||||
const message = document.createElement('div')
|
const message = document.createElement('div')
|
||||||
message.classList.add('table-generator-error-message')
|
message.classList.add('notification-content')
|
||||||
const messageHeader = document.createElement('p')
|
const messageHeader = document.createElement('p')
|
||||||
messageHeader.classList.add('table-generator-error-message-header')
|
const messageHeaderInner = document.createElement('strong')
|
||||||
messageHeader.textContent = view.state.phrase(
|
messageHeaderInner.textContent = view.state.phrase(
|
||||||
'sorry_your_table_cant_be_displayed_at_the_moment'
|
'sorry_your_table_cant_be_displayed_at_the_moment'
|
||||||
)
|
)
|
||||||
|
messageHeader.appendChild(messageHeaderInner)
|
||||||
const messageBody = document.createElement('p')
|
const messageBody = document.createElement('p')
|
||||||
messageBody.textContent = view.state.phrase(
|
messageBody.textContent = view.state.phrase(
|
||||||
'this_could_be_because_we_cant_support_some_elements_of_the_table'
|
'this_could_be_because_we_cant_support_some_elements_of_the_table'
|
||||||
)
|
)
|
||||||
message.appendChild(messageHeader)
|
message.appendChild(messageHeader)
|
||||||
message.appendChild(messageBody)
|
message.appendChild(messageBody)
|
||||||
warning.appendChild(message)
|
messageWrapper.appendChild(message)
|
||||||
|
warning.appendChild(messageWrapper)
|
||||||
const element = document.createElement('div')
|
const element = document.createElement('div')
|
||||||
element.classList.add('table-generator', 'table-generator-error-container')
|
element.classList.add('table-generator', 'table-generator-error-container')
|
||||||
element.appendChild(warning)
|
element.appendChild(warning)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { FC, memo, MouseEventHandler, useCallback, useState } from 'react'
|
import { memo, useCallback, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||||
|
@ -33,54 +33,31 @@ export const CopyToClipboard = memo<{
|
||||||
description={copied ? `${t('copied')}!` : t('copy')}
|
description={copied ? `${t('copied')}!` : t('copy')}
|
||||||
overlayProps={{ delay: copied ? 1000 : 250 }}
|
overlayProps={{ delay: copied ? 1000 : 250 }}
|
||||||
>
|
>
|
||||||
<span>
|
{kind === 'text' ? (
|
||||||
{kind === 'text' ? (
|
<OLButton
|
||||||
<TextButton handleClick={handleClick} />
|
onClick={handleClick}
|
||||||
) : (
|
size="sm"
|
||||||
<IconButton handleClick={handleClick} copied={copied} />
|
variant="secondary"
|
||||||
)}
|
className="copy-button"
|
||||||
</span>
|
bs3Props={{ bsSize: 'xsmall' }}
|
||||||
|
>
|
||||||
|
{t('copy')}
|
||||||
|
</OLButton>
|
||||||
|
) : (
|
||||||
|
<OLIconButton
|
||||||
|
onClick={handleClick}
|
||||||
|
variant="link"
|
||||||
|
size="sm"
|
||||||
|
accessibilityLabel={t('copy')}
|
||||||
|
className="copy-button"
|
||||||
|
bs3Props={{ bsSize: 'xsmall' }}
|
||||||
|
icon={bsVersion({
|
||||||
|
bs5: copied ? 'check' : 'content_copy',
|
||||||
|
bs3: copied ? 'check' : 'clipboard',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</OLTooltip>
|
</OLTooltip>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
CopyToClipboard.displayName = 'CopyToClipboard'
|
CopyToClipboard.displayName = 'CopyToClipboard'
|
||||||
|
|
||||||
const TextButton: FC<{
|
|
||||||
handleClick: MouseEventHandler<HTMLButtonElement>
|
|
||||||
}> = ({ handleClick }) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<OLButton
|
|
||||||
onClick={handleClick}
|
|
||||||
size="sm"
|
|
||||||
variant="secondary"
|
|
||||||
className="copy-button"
|
|
||||||
bs3Props={{ bsSize: 'xsmall' }}
|
|
||||||
>
|
|
||||||
{t('copy')}
|
|
||||||
</OLButton>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const IconButton: FC<{
|
|
||||||
handleClick: MouseEventHandler<HTMLButtonElement>
|
|
||||||
copied: boolean
|
|
||||||
}> = ({ handleClick, copied }) => {
|
|
||||||
const { t } = useTranslation()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<OLIconButton
|
|
||||||
onClick={handleClick}
|
|
||||||
variant="link"
|
|
||||||
size="sm"
|
|
||||||
accessibilityLabel={t('copy')}
|
|
||||||
className="copy-button"
|
|
||||||
bs3Props={{ bsSize: 'xsmall' }}
|
|
||||||
icon={bsVersion({
|
|
||||||
bs5: copied ? 'check' : 'content_copy',
|
|
||||||
bs3: copied ? 'check' : 'clipboard',
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
@import 'editor/share';
|
@import 'editor/share';
|
||||||
@import 'editor/tags-input';
|
@import 'editor/tags-input';
|
||||||
@import 'editor/review-panel-new';
|
@import 'editor/review-panel-new';
|
||||||
|
@import 'editor/table-generator-column-width-modal';
|
||||||
@import 'website-redesign';
|
@import 'website-redesign';
|
||||||
@import 'group-settings';
|
@import 'group-settings';
|
||||||
@import 'templates-v2';
|
@import 'templates-v2';
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
.table-generator-width-modal {
|
||||||
|
.table-generator-width-label {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-generator-usepackage-copy {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: var(--spacing-03) var(--spacing-05);
|
||||||
|
background: var(--bg-light-secondary);
|
||||||
|
border: 1px solid var(--border-primary-dark);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue