table-inserter-dropdown-legacy.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { FC, memo, useCallback, useRef, useState } from 'react'
  2. import * as commands from '../../extensions/toolbar/commands'
  3. import { useTranslation } from 'react-i18next'
  4. import useDropdown from '../../../../shared/hooks/use-dropdown'
  5. import { useCodeMirrorViewContext } from '../codemirror-context'
  6. import OLTooltip from '@/shared/components/ol/ol-tooltip'
  7. import OLOverlay from '@/shared/components/ol/ol-overlay'
  8. import OLPopover from '@/shared/components/ol/ol-popover'
  9. import MaterialIcon from '../../../../shared/components/material-icon'
  10. import classNames from 'classnames'
  11. import { emitToolbarEvent } from '../../extensions/toolbar/utils/analytics'
  12. export const LegacyTableDropdown = memo(() => {
  13. const { t } = useTranslation()
  14. const { open, onToggle, ref } = useDropdown()
  15. const view = useCodeMirrorViewContext()
  16. const target = useRef<any>(null)
  17. const onSizeSelected = useCallback(
  18. (sizeX: number, sizeY: number) => {
  19. onToggle(false)
  20. commands.insertTable(view, sizeX, sizeY)
  21. emitToolbarEvent(view, 'table-generator-insert-table')
  22. view.focus()
  23. },
  24. [view, onToggle]
  25. )
  26. return (
  27. <>
  28. <OLTooltip
  29. hidden={open}
  30. id="toolbar-table"
  31. description={<div>{t('toolbar_insert_table')}</div>}
  32. overlayProps={{ placement: 'bottom' }}
  33. >
  34. <button
  35. type="button"
  36. className="ol-cm-toolbar-button"
  37. aria-label={t('toolbar_insert_table')}
  38. onMouseDown={event => {
  39. event.preventDefault()
  40. event.stopPropagation()
  41. }}
  42. onClick={() => {
  43. onToggle(!open)
  44. }}
  45. ref={target}
  46. >
  47. <MaterialIcon type="table_chart" />
  48. </button>
  49. </OLTooltip>
  50. <OLOverlay
  51. show={open}
  52. target={target.current}
  53. placement="bottom"
  54. container={view.dom}
  55. containerPadding={0}
  56. transition
  57. rootClose
  58. onHide={() => onToggle(false)}
  59. >
  60. <OLPopover
  61. id="toolbar-table-menu"
  62. ref={ref}
  63. className="ol-cm-toolbar-button-menu-popover ol-cm-toolbar-button-menu-popover-unstyled"
  64. >
  65. <div className="ol-cm-toolbar-table-grid-popover">
  66. <SizeGrid sizeX={10} sizeY={10} onSizeSelected={onSizeSelected} />
  67. </div>
  68. </OLPopover>
  69. </OLOverlay>
  70. </>
  71. )
  72. })
  73. LegacyTableDropdown.displayName = 'TableInserterDropdown'
  74. const range = (start: number, end: number) =>
  75. Array.from({ length: end - start + 1 }, (v, k) => k + start)
  76. const SizeGrid: FC<{
  77. sizeX: number
  78. sizeY: number
  79. onSizeSelected: (sizeX: number, sizeY: number) => void
  80. }> = ({ sizeX, sizeY, onSizeSelected }) => {
  81. const [currentSize, setCurrentSize] = useState<{
  82. sizeX: number
  83. sizeY: number
  84. }>({ sizeX: 0, sizeY: 0 })
  85. const { t } = useTranslation()
  86. let label = t('toolbar_table_insert_table_lowercase')
  87. if (currentSize.sizeX > 0 && currentSize.sizeY > 0) {
  88. label = t('toolbar_table_insert_size_table', {
  89. size: `${currentSize.sizeY}×${currentSize.sizeX}`,
  90. })
  91. }
  92. return (
  93. <>
  94. <div className="ol-cm-toolbar-table-size-label">{label}</div>
  95. <table
  96. className="ol-cm-toolbar-table-grid"
  97. onMouseLeave={() => {
  98. setCurrentSize({ sizeX: 0, sizeY: 0 })
  99. }}
  100. >
  101. <tbody>
  102. {range(1, sizeY).map(y => (
  103. <tr key={y}>
  104. {range(1, sizeX).map(x => (
  105. // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
  106. <td
  107. className={classNames('ol-cm-toolbar-table-cell', {
  108. active: currentSize.sizeX >= x && currentSize.sizeY >= y,
  109. })}
  110. key={x}
  111. onMouseEnter={() => {
  112. setCurrentSize({ sizeX: x, sizeY: y })
  113. }}
  114. onMouseUp={() => onSizeSelected(x, y)}
  115. />
  116. ))}
  117. </tr>
  118. ))}
  119. </tbody>
  120. </table>
  121. </>
  122. )
  123. }